I have Contacts and ContactsGroup Two models
contact contains group as m2m relationship
class ContactGroup(models.Model):
contact_group = models.ManyToManyField(ContactGroup, null=True, related_name="contact_list")
and contacts is another model
I want to create bulk_create contacts where contact_group also added on the model.
group_list = []
if group:
groups = [item.strip() for item in group.split(',')]
for item in groups:
try:
group, created = ContactGroup.objects.get_or_create(account=account, name=item)
group_list.append(group)
except :
pass
contact = Contacts(
name = name,
phone = change_phone_format(phone),
email = email,
address = address,
company = company,
website = website,
notes = notes,
dob = dob,
account = account
)
bulk_obj.append(contact)
bulk_group.append(group_list)
ThroughModel = Contacts.contact_group.through
now_date = datetime.datetime.now()
Contacts.objects.bulk_create(bulk_obj)
contacts = Contacts.objects.filter(created_on__gte=now_date)
bulk_through = []
for i, item in enumerate(contacts):
for gr in bulk_group[i]:
if item and gr:
bulk_through.append(ThroughModel(contactgroup_id=item.pk, contacts_id=gr.pk))
ThroughModel.objects.bulk_create(bulk_through)
But shows error
IntegrityError at /contact-manager/contacts/process/goIKlkpymfWCaFeiQXwp/
(1452, 'Cannot add or update a child row: a foreign key constraint fails (`sparrow`.`contactmanager_contacts_contact_group`, CONSTRAINT `D3781be41803f836ec292e41ed99c16a` FOREIGN KEY (`contactgroup_id`) REFERENCES `contactmanager_contactgroup` (`id`))')
Is there any solution ?
Maybe this can help, change last but one line to:
bulk_through.append(ThroughModel(contactgroup_id=gr.pk, contacts_id=item.pk))
seems to me that variables are mixed.
Related
This is the model :
class Requirement(models.Model):
name = models.CharField(max_length=100)
user = models.ForeignKey(
User,on_delete=models.CASCADE, related_name = 'user'
)
assigned_user = models.ForeignKey(
User,related_name = "assigned",on_delete=models.CASCADE,
)
I am running this query:
requirementsOb = Requirement.objects.filter(user = currentUser)
Where currentUser is logged in user. The result returns multiple requriements. I also want to get all user related data. How can i get user related data only for assigned_user
You can try like this:
current_user = request.user
requirements = current_user.user.all() | current_user.assigned.all()
Or you can try this approach:
requirementsOb = Requirement.objects.filter(Q(user = currentUser) | Q(assigned_user=currentUser))
If you want to get user data from requirements, you can try:
for r in requirementsOb:
r.user
r.assigned_user
If you want to get only the first requirement from the requirementsOb, then try like this:
requirement = requirementsOb.first() # or .last() for last object
requirement.user
requirement.assigned_user
More information can be found in documentation.
I want to bulk create objects, when they have a foreign key and their foreign key is not id field. (When to_field value is id you can reference it with model_id in creation but I haven't found a way to do id with another field.)
I have a model named Credit:
class Credit(models.Model):
account = models.ForeignKey('finance.Account', to_field='account_id', on_delete=models.PROTECT)
amount = models.PositiveBigIntegerField()
and a model named Account:
class Account(models.Model):
account_id = models.UUIDField(
verbose_name=_("account id"),
db_index=True,
null=True,
unique=True,
)
and I tried to create objects with:
accounts = [] # list of uuids
credits = [
Credit(
account__account_id=a,
amount=amount,
) for a in accounts]
created_objects = Credit.objects.bulk_create(
credits, ignore_conflicts=True
)
and I get the following error:
TypeError: Credit() got an unexpected keyword argument 'account__account_id'
That's not possible because you are touching two tables: Credit and Account. So you need at least two INSERTs anyways.
accounts_uuids = []
amount = 0
accounts = [Account(account_id=uuid) for uuid in accounts_uuids]
Account.objects.bulk_create(objs=accounts)
credits = [Credit(account=account, amount=amount) for account in accounts]
Credit.objects.bulk_create(objs=credits, ignore_conflicts=True)
My models are:
models.User:
id = pk
username = text
models.Offer
id = pk
description = text
publicationDate = Date
user = Fk(User)
my serializer is:
class UserOfferSerializer(ModelSerializer):
offers = OfferSerializerAll(many=True, read_only=True)
class Meta:
model = User
fields = ('id', 'username', 'offers')
I am trying to apply more than one filter on the queryset:
users = users.filter(offers__publicationDate__range=[startdate, enddate]). prefetch_related(Prefetch('offers', queryset=Offer.objects.filter(
publicationDate__range=[startdate, enddate]))).distinct()
then
users = users.filter(offers__description__icontains=sometext).prefetch_related(Prefetch('offers', queryset=Offer.objects.filter(description__icontains=sometext))).distinct()
First one works fine and the other one throws the following exception:
ValueError: 'offers' lookup was already seen with a different queryset. You may need to adjust the ordering of your lookups.
Update:
My current code is:
if (offerBeginDate != None and offerEndDate != None):
b = offerBeginDate.split('-')
e = offerEndDate.split('-')
startdate = datetime.date(int(b[0]), int(b[1]), int(b[2]))
enddate = datetime.date(int(e[0]), int(e[1]), int(e[2]))
users = users.filter(offers__publicationDate__range=[startdate, enddate])
offers = offers.filter(publicationDate__range=[startdate, enddate])
if (descriptionText != None):
users = users.filter(offers__functionDescription__icontains=descriptionText.strip())
offers = offers.filter(functionDescription__icontains=descriptionText.strip())
users = users.prefetch_related('offers', Prefetch(queryset=offers))
Any help? Thank you all :)))
You can use to_attr argument of Prefetch object to prefetch additional queryset:
users = users.filter(offers__description__icontains=sometext).prefetch_related(
Prefetch('offers', queryset=Offer.objects.filter(
publicationDate__range=[startdate, enddate]), to_attr='date_offers'),
Prefetch('offers', queryset=Offer.objects.filter(description__icontains=sometext), to_attr='description_offers')).distinct()
UPD
If you need dynamically add filters to prefetched queryset you can define it separately like this:
if some_case:
users = users.filter(offers__description__icontains=sometext)
offers=Offer.objects.filter(description__icontains=sometext)
if some_case_2:
users = users.filter(**conditions)
offers = offers.filter(**conditions)
users = users.prefetch_related(Prefetch('offers', queryset=offers))
Now each user in users queryset will have two attributes: user.date_offers and user.description_offers.
I am implementing a web interface for email lists. When a list administrator logs in, the site will visually display which lists they are an owner of and corresponding information about the lists. For this I have decided to have two tables:
1) An owner table which contains entries for information about list administrators. Each of these entries contains a 'ManyToManyField' which holds the information about which lists the owner in any given entry is an administrator for.
2) A list table which contains entries with information about each email list. Each entry contains the name of the list a 'ManyToManyField' holding information about which owners are administrators the list.
Here is the code in models.py:
from django.db import models
class ListEntry(models.Model):
name = models.CharField(max_length=64)
owners = models.ManyToManyField('OwnerEntry')
date = models.DateTimeField('date created')
class Meta:
ordering = ('name',)
class OwnerEntry(models.Model):
name = models.CharField(max_length=32)
lists = models.ManyToManyField('ListEntry')
class Meta:
ordering = ('name',)
I have already set up a simple local database to create a basic working website with. I have populated it with test entries using this code:
from list_app.models import *
from datetime import *
le1 = ListEntry(
name = "Physics 211 email list",
date = datetime.now(),
)
le1.save()
le2 = ListEntry(
name = "Physics 265 email list",
date = datetime(2014,1,1),
)
le2.save()
oe1 = OwnerEntry(
name = 'wasingej',
)
oe1.save()
oe1.lists.add(le1,le2)
le1.owners.add(oe1)
le2.owners.add(oe1)
oe2 = OwnerEntry(
name = 'doej',
)
oe2.save()
oe2.lists.add(le1)
le1.owners.add(oe2)
Here is where my error occurs: When the user has logged in via CAS, I have them redirected to this page in views.py:
def login_success(request):
u = OwnerEntry(name=request.user)
print(u.name)
print(u.lists)
return HttpResponse("login success!")
At the line 'print(u.lists)', I get the error "" needs to have a value for field "ownerentry" before this many-to-many relationship can be used.
What am I doing wrong here?
Your model structure is broken, for a start. You don't need ManyToManyFields on both sides of the relationship, only one - Django will provide the accessor for the reverse relationship.
Your issue is happening because you are not querying an existing instance from the database, you are instantiating an unsaved one. To query, you use model.objects.get():
u = OwnerEntry.objects.get(name=request.user.username)
You need to provide the actual class to the ManyToManyField constructor, not a string.
https://docs.djangoproject.com/en/dev/topics/db/examples/many_to_many/
I initially extended only the Group model, and although I got the extra fields working correctly, I end up with inconsistent results when I switch back to the auth-user model:
group1 = MyGroup(..)
user = group1.user_set.all()[0]
group2 = user.groups.all()[0]
group1 == group2 #(False!)
type(group1) #MyGroup..
type(group2) #Group..
My next thought was to extend both the auth.User and auth.Group models.
Example structure:
from django.contrib.auth.models import User As DjangoUser
from django.contrib.auth.models import Group As DjangoGroup
class MyGroup(DjangoGroup):
extra1 = models.CharField(..)
class MyUser(DjangoUser):
extra1 = models.CharField(..)
Is this possible? I saw a bug-report stating it was fixed here. However I didn't see an example of the correct way to achieve this, nor was it clear if this portion was necessary post bug-fix:
manager = UserManager()
class MyUser(DjangoUser):
signature = forms.CharField()
post_count = forms.IntegerField()
objects = manager
_default_manager = manager
Any ideas/examples of this sort of behavior? I attempted to re-define the 'groups' link in the user model but that led to a validation error. Ideally I would like to be able to run the example above and have group1 == group2 and type(group2) == type(MyGroup())
You can dynamically add a new field to django User/Group models, so that no new class type will be created. For reference, see: http://code.google.com/p/comaie-django-groups/source/browse/trunk/src/comaie/django/groups/models.py?r=5
models.ForeignKey(
Group,
null = True,
blank = True,
related_name = 'children',
verbose_name = _('parent'),
help_text = _('The group\'s parent group. None, if it is a root node.')
).contribute_to_class(Group, 'parent')
def get_all_groups(self):
"""
Returns all groups the user is member of AND all parent groups of those
groups.
"""
direct_groups = self.groups.all()
groups = set()
for group in direct_groups:
ancestors = group.get_ancestors().all()
for anc in ancestors:
groups.add(anc)
groups.add(group)
return groups
setattr(User, 'get_all_groups', get_all_groups)