Alasdair's answer सहायक है, लेकिन मुझे distinct()
का उपयोग करना पसंद नहीं है। यह कभी-कभी उपयोगी हो सकता है, लेकिन आमतौर पर यह एक कोड गंध है जो आपको बताती है कि आपने अपने जुड़ने को गड़बड़ कर दिया है।
सौभाग्य से, Django के queryset आपको सबक्वायरीज़ पर फ़िल्टर करने देता है।
2017-10-06 09:56:22[DEBUG]django.db.backends.execute(): (0.000) PRAGMA foreign_keys; args=None
2017-10-06 09:56:22[DEBUG]django.db.backends.execute(): (0.000) PRAGMA foreign_keys = 0; args=None
2017-10-06 09:56:22[DEBUG]django.db.backends.execute(): (0.000) BEGIN; args=None
2017-10-06 09:56:22[DEBUG]django.db.backends.schema.execute(): CREATE TABLE "udjango_user" ("id" integer NOT NULL PRIMARY KEY AUTOINCREMENT, "email" varchar(254) NOT NULL); (params None)
2017-10-06 09:56:22[DEBUG]django.db.backends.execute(): (0.000) CREATE TABLE "udjango_user" ("id" integer NOT NULL PRIMARY KEY AUTOINCREMENT, "email" varchar(254) NOT NULL); args=None
2017-10-06 09:56:22[DEBUG]django.db.backends.execute(): (0.000) PRAGMA foreign_keys = 0; args=None
2017-10-06 09:56:22[DEBUG]django.db.backends.execute(): (0.000) PRAGMA foreign_keys; args=None
2017-10-06 09:56:22[DEBUG]django.db.backends.execute(): (0.000) PRAGMA foreign_keys = 0; args=None
2017-10-06 09:56:22[DEBUG]django.db.backends.execute(): (0.000) BEGIN; args=None
2017-10-06 09:56:22[DEBUG]django.db.backends.schema.execute(): CREATE TABLE "udjango_report" ("id" integer NOT NULL PRIMARY KEY AUTOINCREMENT, "user_id" integer NOT NULL REFERENCES "udjango_user" ("id")); (params None)
2017-10-06 09:56:22[DEBUG]django.db.backends.execute(): (0.000) CREATE TABLE "udjango_report" ("id" integer NOT NULL PRIMARY KEY AUTOINCREMENT, "user_id" integer NOT NULL REFERENCES "udjango_user" ("id")); args=None
2017-10-06 09:56:22[DEBUG]django.db.backends.schema.execute(): CREATE INDEX "udjango_report_e8701ad4" ON "udjango_report" ("user_id"); (params [])
2017-10-06 09:56:22[DEBUG]django.db.backends.execute(): (0.000) CREATE INDEX "udjango_report_e8701ad4" ON "udjango_report" ("user_id"); args=[]
2017-10-06 09:56:22[DEBUG]django.db.backends.execute(): (0.000) PRAGMA foreign_keys = 0; args=None
2017-10-06 09:56:22[DEBUG]django.db.backends.execute(): (0.000) BEGIN; args=None
2017-10-06 09:56:22[DEBUG]django.db.backends.execute(): (0.000) INSERT INTO "udjango_user" ("email") VALUES ('[email protected]'); args=['[email protected]']
2017-10-06 09:56:22[DEBUG]django.db.backends.execute(): (0.000) BEGIN; args=None
2017-10-06 09:56:22[DEBUG]django.db.backends.execute(): (0.000) INSERT INTO "udjango_user" ("email") VALUES ('[email protected]'); args=['[email protected]']
2017-10-06 09:56:22[DEBUG]django.db.backends.execute(): (0.000) BEGIN; args=None
2017-10-06 09:56:22[DEBUG]django.db.backends.execute(): (0.000) INSERT INTO "udjango_user" ("email") VALUES ('[email protected]'); args=['[email protected]']
2017-10-06 09:56:22[DEBUG]django.db.backends.execute(): (0.000) BEGIN; args=None
2017-10-06 09:56:22[DEBUG]django.db.backends.execute(): (0.000) INSERT INTO "udjango_user" ("email") VALUES ('[email protected]'); args=['[email protected]']
2017-10-06 09:56:22[DEBUG]django.db.backends.execute(): (0.000) BEGIN; args=None
2017-10-06 09:56:22[DEBUG]django.db.backends.execute(): (0.000) INSERT INTO "udjango_report" ("user_id") VALUES (1); args=[1]
2017-10-06 09:56:22[DEBUG]django.db.backends.execute(): (0.000) BEGIN; args=None
2017-10-06 09:56:22[DEBUG]django.db.backends.execute(): (0.000) INSERT INTO "udjango_report" ("user_id") VALUES (3); args=[3]
2017-10-06 09:56:22[DEBUG]django.db.backends.execute(): (0.000) BEGIN; args=None
2017-10-06 09:56:22[DEBUG]django.db.backends.execute(): (0.000) INSERT INTO "udjango_report" ("user_id") VALUES (3); args=[3]
2017-10-06 09:56:22[INFO]root.main(): users without reports
2017-10-06 09:56:22[DEBUG]django.db.backends.execute(): (0.000) SELECT "udjango_user"."id", "udjango_user"."email" FROM "udjango_user" LEFT OUTER JOIN "udjango_report" ON ("udjango_user"."id" = "udjango_report"."user_id") WHERE ("udjango_report"."id" IS NULL AND "udjango_user"."email" LIKE 'a%' ESCAPE '\') LIMIT 21; args=(u'a%',)
2017-10-06 09:56:22[INFO]root.main(): [User(u'[email protected]')]
2017-10-06 09:56:22[INFO]root.main(): users with reports (allows duplicates)
2017-10-06 09:56:22[DEBUG]django.db.backends.execute(): (0.000) SELECT "udjango_user"."id", "udjango_user"."email" FROM "udjango_user" INNER JOIN "udjango_report" ON ("udjango_user"."id" = "udjango_report"."user_id") WHERE ("udjango_report"."id" IS NOT NULL AND "udjango_user"."email" LIKE 'a%' ESCAPE '\') LIMIT 21; args=(u'a%',)
2017-10-06 09:56:22[INFO]root.main(): [User(u'[email protected]'), User(u'[email protected]'), User(u'[email protected]')]
2017-10-06 09:56:22[INFO]root.main(): users with reports (no duplicates)
2017-10-06 09:56:22[DEBUG]django.db.backends.execute(): (0.000) SELECT "udjango_user"."id", "udjango_user"."email" FROM "udjango_user" WHERE (NOT ("udjango_user"."id" IN (SELECT U0."id" AS Col1 FROM "udjango_user" U0 LEFT OUTER JOIN "udjango_report" U1 ON (U0."id" = U1."user_id") WHERE U1."id" IS NULL)) AND "udjango_user"."email" LIKE 'a%' ESCAPE '\') LIMIT 21; args=(u'a%',)
2017-10-06 09:56:22[INFO]root.main(): [User(u'[email protected]'), User(u'[email protected]')]
2017-10-06 09:56:22[INFO]root.main(): users with reports (no duplicates, simpler SQL)
2017-10-06 09:56:22[DEBUG]django.db.backends.execute(): (0.000) SELECT "udjango_user"."id", "udjango_user"."email" FROM "udjango_user" WHERE ("udjango_user"."email" LIKE 'a%' ESCAPE '\' AND "udjango_user"."id" IN (SELECT U0."user_id" FROM "udjango_report" U0)) LIMIT 21; args=(u'a%',)
2017-10-06 09:56:22[INFO]root.main(): [User(u'[email protected]'), User(u'[email protected]')]
2017-10-06 09:56:22[INFO]root.main(): Done.
:
# Tested with Django 1.9.2
import logging
import sys
import django
from django.apps import apps
from django.apps.config import AppConfig
from django.conf import settings
from django.db import connections, models, DEFAULT_DB_ALIAS
from django.db.models.base import ModelBase
NAME = 'udjango'
def main():
setup()
class User(models.Model):
email = models.EmailField()
def __repr__(self):
return 'User({!r})'.format(self.email)
class Report(models.Model):
user = models.ForeignKey(User)
syncdb(User)
syncdb(Report)
anne = User.objects.create(email='[email protected]')
User.objects.create(email='[email protected]')
alice = User.objects.create(email='[email protected]')
User.objects.create(email='[email protected]')
Report.objects.create(user=anne)
Report.objects.create(user=alice)
Report.objects.create(user=alice)
logging.info('users without reports')
logging.info(User.objects.filter(report__isnull=True, email__startswith='a'))
logging.info('users with reports (allows duplicates)')
logging.info(User.objects.filter(report__isnull=False, email__startswith='a'))
logging.info('users with reports (no duplicates)')
logging.info(User.objects.exclude(report__isnull=True).filter(email__startswith='a'))
logging.info('users with reports (no duplicates, simpler SQL)')
report_user_ids = Report.objects.values('user_id')
logging.info(User.objects.filter(id__in=report_user_ids, email__startswith='a'))
logging.info('Done.')
def setup():
db_file = NAME + '.db'
with open(db_file, 'w'):
pass # wipe the database
settings.configure(
DEBUG=True,
DATABASES={
DEFAULT_DB_ALIAS: {
'ENGINE': 'django.db.backends.sqlite3',
'NAME': db_file}},
LOGGING={'version': 1,
'disable_existing_loggers': False,
'formatters': {
'debug': {
'format': '%(asctime)s[%(levelname)s]'
'%(name)s.%(funcName)s(): %(message)s',
'datefmt': '%Y-%m-%d %H:%M:%S'}},
'handlers': {
'console': {
'level': 'DEBUG',
'class': 'logging.StreamHandler',
'formatter': 'debug'}},
'root': {
'handlers': ['console'],
'level': 'INFO'},
'loggers': {
"django.db": {"level": "DEBUG"}}})
app_config = AppConfig(NAME, sys.modules['__main__'])
apps.populate([app_config])
django.setup()
original_new_func = ModelBase.__new__
# noinspection PyDecorator
@staticmethod
def patched_new(cls, name, bases, attrs):
if 'Meta' not in attrs:
class Meta:
app_label = NAME
attrs['Meta'] = Meta
return original_new_func(cls, name, bases, attrs)
ModelBase.__new__ = patched_new
def syncdb(model):
""" Standard syncdb expects models to be in reliable locations.
Based on https://github.com/django/django/blob/1.9.3
/django/core/management/commands/migrate.py#L285
"""
connection = connections[DEFAULT_DB_ALIAS]
with connection.schema_editor() as editor:
editor.create_model(model)
main()
आप एक अजगर फ़ाइल में है कि डाल दिया और इसे चलाने के हैं, तो आप कुछ इस तरह देखना चाहिए:
यहाँ अपने प्रश्न के सवालों को चलाने के लिए कुछ तरीके हैं आप देख सकते हैं कि अंतिम क्वेरी सभी आंतरिक जोड़ों का उपयोग करती है।
यह ठीक है, लेकिन यह '__isnull = True' और' __isnull = गलत 'दोनों के मामले में' रिपोर्ट 'के साथ' बाहरी जॉइन 'उत्पन्न करता है। रिपोर्ट वाले उपयोगकर्ताओं के बारे में प्रश्न के लिए यह 'इनर जॉइन' से कम कुशल हो सकता है। मुझे इस मामले के लिए एक बदसूरत हैक मिला है: 'User.objects.filter (report__id__gt = 0) .distinct()'। यह मानता है कि आईडी> 0 हैं, जिन्हें एक मामला नहीं होना चाहिए। किसी भी शामिल होने के लिए मजबूर करने का कोई बेहतर तरीका, कोई भी? –