Django bulk_create function example - python

I'm trying to understand bulk_create in Django
This was my original query I'm trying to convert:
for e in q:
msg = Message.objects.create(
recipient_number=e.mobile,
content=batch.content,
sender=e.contact_owner,
billee=batch.user,
sender_name=batch.sender_name
)
Does that mean doing the following (below) will loop and create all the entries first then hit the database? Is this right?
msg = Message.objects.bulk_create({
Message (
recipient_number=e.mobile,
content=batch.content,
sender=e.contact_owner,
billee=batch.user,
sender_name=batch.sender_name
),
})

The second code in the question create a single object, because it pass a set with a Message object.
To create multiple objects, pass multiple Message objects to bulk_create. For example:
objs = [
Message(
recipient_number=e.mobile,
content=batch.content,
sender=e.contact_owner,
billee=batch.user,
sender_name=batch.sender_name
)
for e in q
]
msg = Message.objects.bulk_create(objs)

The Official Example:
class Entry(models.Model):
blog = models.ForeignKey(Blog, on_delete=models.CASCADE)
headline = models.CharField(max_length=255)
body_text = models.TextField()
pub_date = models.DateField()
mod_date = models.DateField()
Now, to Bulk Create
Entry.objects.bulk_create([
Entry(headline='This is a test'),
Entry(headline='This is only a test'),
])

name = request.data.get('name')
period = request.data.get('period')
email = request.data.get('email')
prefix = request.data.get('prefix')
bulk_number = int(request.data.get('bulk_number'))
bulk_list = list()
for _ in range(bulk_number):
code = code_prefix + uuid.uuid4().hex.upper()
bulk_list.append(
DjangoModel(name=name, code=code, period=period, user=email))
bulk_msj = DjangoModel.objects.bulk_create(bulk_list)

Related

Django REST: ignoring custom fields which are not part of model

My TimeReport model looks like this:
class TimeReport(models.Model):
minutes_spent = models.PositiveIntegerField()
task = models.ForeignKey(Task, on_delete=models.CASCADE)
created_at = models.DateTimeField(auto_now_add=True)
modified_at = models.DateTimeField(auto_now=True)
reported_for = models.DateField()
note = models.TextField(null = True, blank=True)
status = models.CharField(max_length=50, choices=State.choices, default=State.new)
user = models.ForeignKey(User, on_delete=models.PROTECT)
And my model serializer:
class TimeReportCreateSerializer(serializers.ModelSerializer):
class Meta:
model = TimeReport
fields = (
'id',
'minutes_spent',
'reported_for',
'note',
'status',
'task_custom_id',
)
task_custom_id = serializers.CharField()
def create(self, validated_data):
user = User.objects.get(auth_user_id = self.context['user_id'])
task = Task.objects.filter(custom_id = validated_data['task_custom_id']).filter(user = user.id).first()
report = TimeReport(**validated_data)
report.user = user
report.task = task
report.save()
return report
So, the problem is, that I want to take a custom value in a serializer, which is not a part of a model and do some custom logic with it - in this case search for the right 'task' in the database. But when I try to parse the model by using report = TimeReport(**validated_data), it gives me an exception:
TypeError at /api/report/
TimeReport() got an unexpected keyword argument 'task_custom_id'
Im kind of new to Django and python itself, so - what is the best approach?
If you are going to use that field only for creation, you should use write_only option.
task_custom_id = serializers.CharField(write_only=True)
See the docs here https://www.django-rest-framework.org/api-guide/fields/#write_only
You just need to remove task_custom_id from the dictionary
class TimeReportCreateSerializer(serializers.ModelSerializer):
class Meta:
model = TimeReport
fields = (
'id',
'minutes_spent',
'reported_for',
'note',
'status',
'task_custom_id',
)
task_custom_id = serializers.CharField()
def create(self, validated_data):
user = User.objects.get(auth_user_id = self.context['user_id'])
task_custom_id = validated_data.pop("task_custom_id")
task = Task.objects.filter(custom_id = task_custom_id).filter(user = user.id).first()
report = TimeReport(**validated_data)
report.user = user
report.task = task
report.save()
return report
task = Task.objects.filter(custom_id = validated_data.pop('task_custom_id')).filter(user = user.id).first()
the **validated_data will return (task_custom_id=value, field1=value1 ...) and task_custom_id it's not a TimeReport field so all u need is to pop it from validated_data before calling the constructor TimeReport

I want to Compare two tables Column (Table1 - Balance_sheet, Table2- Account_list) (Column-split,column-account) and get the similar data in django

models.py:
class Balance_Sheet(models.Model): #name of the table
# date = models.DateField() # Name of the column
# transaction_type = models.CharField(max_length=100,blank=False)
# num = models.IntegerField()
name = models.CharField(max_length=100,blank=True)
# description = models.CharField(max_length=100,blank=True)
split = models.CharField(max_length=100,blank=False)
# class Meta:
# abstract : True
class Account_List(models.Model):
account = models.CharField(max_length=100,blank=True,null=True)
type = models.CharField(max_length=100,blank=True, null=True)
split =models.ForeignKey(Balance_Sheet,null=False, default=True,on_delete=models.CASCADE)
def __str__(self):
return 'Account : {0} Type : {1} '.format(self.account,self.type)
views.py:
def DisplayUVL(request):
# Excel page changes
Ven_list = Balance_Sheet.objects.filter(account_list__isnull=True).values_list('split', flat=True)
print("SQL Query:",Ven_list.query)
context = {
'items': Ven_list
# 'header': 'Vendor List'
}
return render(request, 'services2.html', context)
select_relations might be helpful to you to compare two table information and get the common one. select_relations is the native way.
If you are using postgressql you can use inner join SQL queries directly.
This question might helpful for you.

how to apply a condition to a queryset in django

I am new to programming, I have a doubt I formed the QuerySet with table data i want to know how to apply condition to the formed queryset and get the count.
Code :
final_set = TaskMaster.objects.filter(istaskactive=True)
I want something like
no_of_rebuild_task = final_set..objects.filter(tasktype.id=1).count
model.py
class TaskMaster(models.Model):
sid = models.CharField(max_length=3)
# Remember to change the default value in processor in production
processor = models.ForeignKey(User,null=True,on_delete=models.CASCADE,default=1)
tasktype = models.ForeignKey(TaskTypeTable, null=True,on_delete=models.CASCADE)
task_title = models.TextField(null=True)
task_description = models.TextField(null=True)
datacenter = models.ForeignKey(DatacenterTable,null=True,on_delete=models.CASCADE)
priority = models.ForeignKey(PriorityTable, null=True,on_delete=models.CASCADE)
status = models.ForeignKey(StatusTable, default=1,on_delete=models.CASCADE)
pid = models.IntegerField(null=True)
sourceincident = models.CharField(max_length=250,null=True)
errorincident = models.CharField(max_length=250,null=True)
processingteam =
models.ForeignKey(TeamTable,null=True,on_delete=models.CASCADE)
createddate = models.DateField(("Date"), default=datetime.date.today)
duedate = models.DateField(("Date"), default=datetime.date.today)
istaskactive = models.BooleanField(default=True)
In Django ORM you can use count() to count the number of records in the selected table.
So for your query it can be
no_of_rebuild_task = TaskMaster.objects.filter(istaskactive=True, tasktype_id=1).count()
See effective way of Django ORM
and count() here.
no_of_rebuild_task = final_set.filter(tasktype__id=1).count()

Django : get the last item of manytomanyfield

With these models :
class Message(models.Model):
text = models.CharField(max_length=200)
date_send = models.DateTimeField(auto_now_add=True,editable=False)
emeteur = models.ForeignKey(User,null=True,related_name="+")
class Meta :
abstract = True
class MessagePerso(Message) :
read_at = models.DateTimeField(("read at"), null=True, blank=True)
class Conversation(models.Model):
title = models.CharField(max_length=90)
creator = models.ForeignKey(User,null=True,related_name="CreatorConversation")
recipient = models.ForeignKey(User,null=True,related_name="RecipientConversation")
created_at = models.DateTimeField(auto_now_add=True,editable=False)
messages = models.ManyToManyField(MessagePerso)
So, for each Conversation I want the text of the last MessagePerso created (ManyToManyField in Conversation) and others informations.
So for now, I have this :
def .. :
u = request.user
conversations = Conversation.objects.filter(Q(creatorr=u)|Q(destinataire=u)).annotate(nbMsg=Count('messages'),date=Max('messages__date_send')).order_by('date','id')
I don't have the the text of last message created for each Conversation, how makes it ?
You can order your data by a date_send field ascending as follow:
class Message(models.Model):
text = models.CharField(max_length=200)
date_send = models.DateTimeField(auto_now_add=True,editable=False)
emeteur = models.ForeignKey(User,null=True,related_name="+")
class Meta :
abstract = True
ordering = ['date_send'] # default ordrer while fetching data
Than for each conversation's messages you fetch the last using .last():
def .. :
u = request.user
conversation_id_list = Conversation.objects.filter(Q(creatorr=u)|Q(destinataire=u)).values_list('id', flat=True)
message_list = list(()
for id in conversation_id_list:
last_message = MessagePerso.objects.filter(conversation_id=id).last()
message_list.append(last_message)
print(last_message.text)
if the number of conversation is kind of big and you want to minimize db queries you can use prefetch_related
def .. :
u = request.user
conversation_list = Conversation.objects.filter(Q(creatorr=u)|Q(destinataire=u)).preftech_related('messages')
messages_dict =dict()
for conversation in conversation_list:
messages_dict.update({
converstaion.id: conversation.messages.all()
})
last_message_list = list()
for conversation_id, message_list in messages_dict.items():
if message_list:
last_message = messages_dict.get(conversation_id)[len(message_list) -1:]
last_message_list.append(last_message)
print(last_message.text)

Django JOIN not Working

My model is like this
class NounPlural(models.Model):
idnoun_plural = models.IntegerField(db_column='idNoun_Plural', primary_key=True) # Field name made lowercase.
nns = models.TextField(db_column='NNS', blank=True) # Field name made lowercase.
news_idnews = models.ForeignKey(News, db_column='news_idnews')
class News(models.Model):
idnews = models.IntegerField(primary_key=True)
source = models.TextField(blank=True)
title = models.TextField(blank=True)
My view.py is like this
def allobj(request):
obj_json = serializers.serialize('json', NounPlural.objects.select_related('news_idnews')[:5] )
obj_list = json.loads( obj_json )
json_data = json.dumps( obj_list )
return HttpResponse( json_data, content_type='application/json' )
All I want to do is to get the NounPlural and also the title from News.When I go to allobj link I only get NounPlural.
In the django documentation related to your question, I always see the need for a .get(id=<something>) with the select_related() call, like so:
Book.objects.select_related('person__city').get(id=4)
So shouldn't your call be:
NounPlural.objects.select_related('news_idnews').get(id=<Newsid>)[:5]
Is this the reason you only have a NounPlural and not the QuerySet you want ?

Categories