How to insert ManyToMany field in django - python

I want to insert a ManyToMany fields in my db using django.I select some customers using checkboxes.
This is my models.py :
class Campaign(models.Model):
title = models.CharField(max_length=255)
channel = models.CharField(max_length=255)
start_date = models.DateField()
end_date = models.DateField()
target_prospect = models.ManyToManyField(ProspectClient,related_name='campaigns_prospect')
target_partner = models.ManyToManyField(PartnerClient,related_name='campaigns_partners')
I try the code below in my views.py but didn't work :
def campaigns_page(request):
if request.user.is_authenticated:
if request.user.profile == 'D' or request.user.profile == 'E' or request.user.is_superuser:
campaigns = Campaign.objects.all()
prospects = ProspectClient.objects.all()
partners = PartnerClient.objects.exclude(id__in=PartnerClient.objects.values('id')).all()
context = {
'campaigns':campaigns,
'prospects':prospects,
'partners':partners
}
if request.method == 'POST':
title = request.POST['title']
channel = request.POST['channel']
start_date = request.POST['start_date']
end_date = request.POST['end_date']
descriptions = request.POST['goals'].split(",")
targets = request.POST['targets']
campaign = Campaign.objects.create(title=title,channel=channel,start_date=start_date,end_date=end_date)
for description in descriptions:
goal = Goal.objects.create(description=description)
goal.campaign.add(campaign)
for target in targets:
prospects.campaign.add(campaign)
partners.campaign.add(campaign)
return render(request,'CampaignManagement/campaigns_page.html',context)
return render(request, 'Login/logout.html')
If I delete the part of tergets it works.
But with this part it gives me This error : 'QuerySet' object has no attribute 'campaign'
How I can solve this ?

I see a couple of errors. Perhaps one or more are leading to the problem.
One
Try printing this:
partners = PartnerClient.objects.exclude(id__in=PartnerClient.objects.values('id')).all()
print(partners)
I suspect it will print None since you are excluding all id's in PartnerClient.objects.values('id'). On another note you don't need the all() since exclude() will return all the results you are looking for.
Two
In the line for target in targets: what exactly are you iterating through? targets = request.POST['targets'] is just giving you a string, so it would iterate through each letter. Perhaps you meant:
targets = request.POST['targets'].split(", ")
like you did for descriptions? Or perhaps you are getting a list of items from your form, in which case you can use:
targets = request.POST.getlist('targets')

Related

Django query filter by another dataset

I have 2 User models:
User: Default user model:
Account: Custom User model, which is an extension of the defualt user model, as I wanted to add a custom field to it called 'Status'.
The problem is that I wanted to filter the data based on the current User, so id usually do something like:
Account.objects.filter(usernmae = User).values_list('status', flat=True)
The problem is that the Account dataset doesnt have the username but they both have the same ID.
I was thinking of doing something like this:
Status = Account.objects.filter(user_id=User.objects.filter(username = user).values_list('id', flat=True)).values_list('status', flat=True)
But then i get the following error:
I imagine there is a way better way of doing it, if yall could help me out.
Views.py:
def upload_audits(request):
form = audits_form(request.POST or None, request.FILES or None)
if form.is_valid():
form.save()
form = audits_form()
obj = Csv_Audit.objects.get(activated=True)
with open(obj.file_name.path,'r') as f:
#to clear model contents before applying new data
auditsModel.objects.all().delete()
reader = csv.reader(f)
for i,row in enumerate(reader):
if i==0:
pass
else:
user = row[1] # gets data from CSV Table and returns username
Status = Account.objects.filter(user_id = request.user).values_list('status')
auditsModel.objects.create(
qs_login = user,
Status = Status,
)
obj.activated = True
obj.save()
return render(request,"backend/uploads.html",{'form':form})
Accounts.py(Model)
class Account(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE)
status = models.CharField(('Status'), max_length=200, default='',choices = [('Bau','Bau'),('Week 1','Week 1')])
def __str__(self):
return self.user.username
1 Answer:mahdi rahimi
I tried your method with the following code:
Status = Account.objects.filter(user__username = user).values_list('status', flat=True)
Which resulted in the following error:
And then I thought of doing this:
Status = Account.objects.filter(user = user).values_list('status', flat=True)
But i got this error:
Which actually returns the usernmae but it seems to be asking for an int?
based on my experience, you can simply join the two tables, and get what you want. roughly, it translates to this:
result = Account.objects.filter(user__username = user).values_list('status', flat=True)
or you can do two queries if you are comfortable with that.
found_user_id = User.objects.filter(username = user).values_list('id', flat = True)
result = Account.objects.filter(user_id = found_user_id).values_list('status', flat=True)
hope that helped.

How do I get row from django database?

Hello I am trying to create a clockIn clockOut website and I do not know how to get a row filtered by a persons name to add in the clock out time.
Here is the code. The first if statement is working fine but the else statement is where I am having trouble doing:
if response.POST.get("clockIn"):
if form.is_valid():
n = form.cleaned_data["name"]
t = Name(name = n, timeIn=datetime.now(), timeOut=NULL)
t.save()
else:
if form.is_valid():
n = form.cleaned_data["name"]
t = Name.objects
t = t.filter(name = n)
s = t(timeOut = datetime.now())
s.save()
Here is my models.py:
class Name(models.Model):
name = models.CharField(max_length=200)
timeIn = models.DateTimeField()
timeOut = models.DateTimeField(default=datetime.now())
def __str__(self):
return self.name
if form.is_valid():
n = form.cleaned_data["name"]
# If there are unique entries for this name then you should use get method instead of filter
try:
t = Name.objects.get(name=n)
t.timeOut = datetime.now()
t.save()
except Exception as _: # or maybe NameDoesNotExist exception
# Handle case
pass
You didn't give enough information to solve this issue properly . Where is your models.py file ? You should add models.py file with your question .
By the way , in Django, to get a row using filter is as like as below :
name=your_person_name
Entry.objects.filter(person_name=name)

Django : Best way to Query a M2M Field , and count occurences

class Edge(BaseInfo):
source = models.ForeignKey('Node', on_delete=models.CASCADE,related_name="is_source")
target = models.ForeignKey('Node', on_delete=models.CASCADE,related_name="is_target")
def __str__(self):
return '%s' % (self.label)
class Meta:
unique_together = ('source','target','label','notes')
class Node(BaseInfo):
item_type_list = [('profile','Profile'),
('page','Page'),
('group','Group'),
('post','Post'),
('phone','Phone'),
('website','Website'),
('email','Email'),
('varia','Varia')
]
item_type = models.CharField(max_length=200,choices=item_type_list,blank = True,null=True)
firstname = models.CharField(max_length=200,blank = True, null=True)
lastname = models.CharField(max_length=200,blank = True,null=True)
identified = models.BooleanField(blank=True,null=True,default=False)
username = models.CharField(max_length=200, blank=True, null=True)
uid = models.CharField(max_length=200,blank=True,null=True)
url = models.CharField(max_length=2000,blank=True,null=True)
edges = models.ManyToManyField('self', through='Edge',blank = True)
I have a Model Node (in this case a soc media profile - item_type) that has relations with other nodes (in this case a post). A profile can be the author of a post. An other profile can like or comment that post.
Question : what is the most efficient way to get all the distinct profiles that liked or commented on anothes profile's post + the count of these likes /comments.
print(Edge.objects.filter(Q(label="Liked")|Q(label="Commented"),q).values("source").annotate(c=Count('source')))
Gets me somewhere but i have the values then (id) and i want to pass the objects to my template rather then .get() all the profiles again...
Result :
Thanks in advance
I ended up with iterating over the queryset and adding the objects that i wanted in a dictionary , if the object was already in dictionary , i would count +1 and add the relation in a nested list.
This doesnt feel right but works for now.
posts = Edge.objects.filter(source = self,target__item_type='post',label='Author')
if posts:
q = Q()
for post in posts:
q = q | Q(target=post.target)
contributors = Edge.objects.filter(Q(label="Liked")|Q(label="Commented"),q)
if contributors:
for i in contributors:
if i.source.uid in results:
if i.label in results[i.source.uid]['relation']:
pass
else:
results[i.source.uid]["relation"].append(i.label)
if 'post' in results[i.source.uid]:
results[i.source.uid]['post'].append(i.target)
else:
results[i.source.uid]['post']=[i.target]
else:
results[i.source.uid] = {'profile' : i.source , 'relation':[i.label],'post':[i.target]}

Calculating the difference between two fields within a table in Django

I have a model which stores the opening and closing balances of a petrol station. I have an additional third column which is basically the difference between the opening and reading values.
class DailySales(models.Model):
PUMP_NAMES = (
...
)
Pump_name = models.CharField(max_length = 5, choices = PUMP_NAMES)
Opening_reading = models.IntegerField()
Closing_reading = models.IntegerField()
Gross_sales = models.IntegerField(null = True)
Date = models.DateField(auto_now_add= True)
def Calc_gross(self):
self.Gross_sales = self.Opening_reading - self.Closing_reading
super(DailySales,self).save()
the Calc_gross method works when i'm saving only one instance at a time.
But i want to add multiple opening and closing values to the model at once for which i'm using formsets.
SalesForm = modelformset_factory(DailySales, extra = 7, exclude=('Date','Gross_sales'))
This is where the logic falters. Django isnt able to calculate the gross values for each row.
Exception Value:
'list' object has no attribute 'Calc_gross'
I was thinking since its a list , I could iterate over each and invoke the Calc_gross method. What will be the name of the list?
Is there a better way to do this? Would it be logical to use Prefixes (how would u assign a prefix to each form?)
Turns out i could just loop over the formset.
if request.method == 'POST':
sale_Form = SalesForm(data = request.POST)
for Form in sale_Form:
if Form.is_valid():
gross = Form.save()
gross.Calc_gross()
gross.save()
else:
print(sale_Form.errors)

django get_or_create method always results in a new record

Model
class projects(models.Model):
"""Table that holds the details of the projects."""
toiName = models.CharField(max_length=100)
toiOwner = models.CharField(max_length=50)
receiver = models.CharField(max_length=50)
manager = models.CharField(max_length=50)
toiOwnerEmail = models.EmailField(max_length=70)
receiverEmail = models.EmailField(max_length=70)
managerEmail = models.EmailField(max_length=70)
dateUpdated= models.DateTimeField(default=datetime.today())
dateCreated = models.DateTimeField(default=datetime.today())
class Meta:
db_table="projects"
View, the original code to save the model works fine, when I go ahead and edit the form in the view, I always end up with a new record.
data = model_to_dict(projects.objects.filter(toiName=pid, managerEmail=request.user)[0])
if request.method == 'POST':
form = projectsForm(request.POST)
if form.is_valid():
#form = projectsForm(request.POST, instance=projects.objects.get(toiName=pid))
#obj = projects\
obj, created = projects.objects.get_or_create\
(toiName=request.POST['toiName'],
toiOwnerEmail=request.POST['toiOwnerEmail'],
toiOwner=request.POST['toiOwner'],
manager=request.POST['manager'],
receiver=request.POST['receiver'],
receiverEmail=request.POST['receiverEmail'],
dateUpdated=datetime.now(),
dateCreated=data['dateCreated'],
managerEmail=request.user,)
Here created always results in True.
At least this dateUpdated=datetime.now() causes get_or_create to always create new record, because each time datetime.now() is different.
I believe I was using the get_or_create incorrectly, since I was only trying to update the entry.
I fixed the code in the view with:
data = model_to_dict(projects.objects.filter(toiName=pid, managerEmail=request.user)[0])
proj = projects.objects.get(toiName=pid, managerEmail=request.user)
if request.method == 'POST':
form = projectsForm(request.POST)
if form.is_valid():
proj.toiName=form.cleaned_data['toiName']
proj.toiOwnerEmail=form.cleaned_data['toiOwnerEmail']
proj.toiOwner=form.cleaned_data['toiOwner']
proj.manager=form.cleaned_data['manager']
proj.receiver=form.cleaned_data['receiver']
proj.receiverEmail=form.cleaned_data['receiverEmail']
proj.dateUpdated=datetime.now()
#proj.dateCreated=data['dateCreated']
proj.save()
additional to #user1865366 answer, projects.objects.get should be enclose it with try ... except ... like so
try:
proj = Projects.objects.get(toiName=pid,manageEmail=request.user)
except Projects.DoesNotExist :
# do something create new proj and do something with the form
...
otherwise there will be big error screen when django cannot get the object

Categories

Resources