I need to create the new object or just update if already existing. I receive: QuerySet' object has no attribute "seat". Don't know what I'm doing wrong.
models:
class rows_and_seats(models.Model):
movie = models.ForeignKey(Movies, on_delete=models.CASCADE)
row = models.CharField(max_length = 1)
number = models.IntegerField()
def __str__(self):
return f'{self.movie}'
class Reservation(models.Model):
customer = models.ForeignKey(User, on_delete=models.CASCADE)
movie = models.ForeignKey(Movies, on_delete=models.CASCADE)
seat = models.ManyToManyField(rows_and_seats)
ordered = models.DateTimeField(default=datetime.now().strftime("%Y-%m-%d %H:%M:%S"), blank=True, null=True)
def __str__(self):
return f'{self.customer.username}:{self.movie.title}:{self.ordered}'
views
#login_required
def buy_seats(request, pk):
if request.method == "POST" and request.session.get("seats"):
seats = request.session.pop("seats")
movie = Movies.objects.get(pk=pk)
customer = User.objects.get(pk=request.user.id)
for s in seats:
user_reserved_seats = rows_and_seats.objects.get(movie=movie, row=s[:1], number=int(s[2:]))
reservation_check = Reservation.objects.filter(customer=customer, movie=movie)
if reservation_check.exists():
reservation_check.seat.add(user_reserved_seats)
else:
new_reservation = Reservation.objects.create(customer=customer, movie=movie)
new_reservation.seat.add(user_reserved_seats)
messages.success(request,"You have succesfully reserved the seats.")
return redirect("home")
return redirect("home")
My goal is to keep rows_and_seat in manyTomany in order to display only one reservation of user in admin panel, instead of the list of repeating itself titles.
You can access the value after the exists() check:
if reservation_check.exists():
reservation_check.first().seat.add(user_reserved_seats)
else:
new_reservation = Reservation.objects.create(customer=customer, movie=movie)
new_reservation.seat.add(user_reserved_seats)
Maybe you can use something like get_or_create:
user_reserved_seats = rows_and_seats.objects.get(movie=movie, row=s[:1], number=int(s[2:]))
reservation, created = Reservation.objects.get_or_create(
customer=customer, movie=movie,
)
reservation.seat.add(user_reserved_seats)
Also you might be looping over the seats too many times, maybe you can add all the seats in only one assignment.
Related
I want to give users ten point each time they fill out one Survey , so i have this code above and now how to add the 10 point to self user after he fill out one
models.py :
class User(AbstractUser):
user_pic = models.ImageField(upload_to='img/',default="",null=True, blank=True)
coins = models.IntegerField(default=10)
def get_image(self):
if self.user_pic and hasattr(self.user_pic, 'url'):
return self.user_pic.url
else:
return '/path/to/default/image'
def give_coins(user, count):
user.coins = F('coins') + count
user.save(update_fields=('coins',))
user.refresh_from_db(fields=('coins',))
class Survey(models.Model):
name = models.CharField(max_length=200)
published_on = models.DateTimeField('Published DateTime')
def __str__(self):
return self.name
def was_published_recently(self):
now = timezone.now()
return now - datetime.timedelta(days=1) <= self.published_on <= now
was_published_recently.admin_order_field = 'published_on'
was_published_recently.boolean = True
was_published_recently.short_description = 'Published recently?'
class Participant(models.Model):
survey = models.ForeignKey(Survey, on_delete=models.CASCADE)
participation_datetime = models.DateTimeField('Participation DateTime')
def __str__(self):
return "Participant "+str(self.participation_datetime)
class Question(models.Model):
survey = models.ForeignKey(Survey, on_delete=models.CASCADE)
question_text = models.CharField(max_length=200)
created_on = models.DateTimeField('Creation DateTime')
def __str__(self):
return self.question_text
views.py :
#register.inclusion_tag('survey/survey_details.html', takes_context=True)
def survey_details(context, survey_id):
survey = Survey.objects.get(id=survey_id)
return {'survey': survey}
#require_http_methods(["POST"])
def submit_survey(request):
form_data = request.POST.copy()
form_items = list(form_data.items())
print("form_items", form_items)
form_items.pop(0) # the first element is the csrf token. Therefore omit it.
survey = None
for item in form_items:
# Here in 'choice/3', '3' is '<choice_id>'.
choice_str, choice_id = item
choice_id = int(choice_id.split('/')[1])
choice = Choice.objects.get(id=choice_id)
if survey is None:
survey = choice.question.survey
choice.votes = choice.votes + 1
choice.save()
if survey is not None:
participant = Participant(survey=survey, participation_datetime=timezone.now())
participant.save()
return redirect('/submit_success/')
so what i must to do if i want to add 10 point to user after he complete one survey
If submit_survey is a call that requires authentication the user will be present on the request request.user.
Add the coins by adding request.user.give_coins(count=10) to the submit_query method.
you have 2 way
work with event driven tools(maybe hard but principled)
set give_coin befor participant.save() on submit_survey
anyway I din't notice, coin is on your absUser model but your Participant has nothing to do with it or relations
Have a models:
class Product(models.Model):
user = models.ForeignKey(User, on_delete=models.CASCADE)
name = models.CharField(max_length=50)
variation_1 = models.BooleanField(default=True)
variation_2 = models.BooleanField(default=True)
variation_3 = models.BooleanField(default=True)
class Order(models.Model):
buyer = models.ForeignKey(User, related_name='buyer')
product = models.ForeignKey(Product)
variations_select = models.CharField(max_length=50, choices=VARIATIONS)
in forms.py
class OrderForm(forms.ModelForm):
variations_select = forms.ChoiceField(choices=VARIATIONS)
class Meta:
model = Order
fields = [
'variations_select'
]
i need to create a clean function that will check if variation_1 or variation_2 or variation_3 are availiable in Product. For this a need request Product.id to def clean_variations_select(self): How to do this?
def clean_variations_select(self):
product = Product.object.get(id = product.id)
variations_select = self.cleaned_data.get("variations_select")
if variations_select == "Variation_1" and product.variation_1 == False:
raise forms.ValidationError("variation_1 was sold already")
else:
return variations_select
product = Product.object.get(id = product.id) - don't work cause Order isn't created to database yet(but in rendering view link to new order creation i have that ../product.id/new_order).
You need to define an __init__ method for your class which should accept your product id as an argument.
def __init__(self,*args,**kwargs):
self.product_id = kwargs.pop('product_id')
super(OrderForm,self).__init__(*args,**kwargs)
When you initialize your form, you pass your product_id as a keyword argument.
OrderForm(request.POST, product_id=product_id)
And in clean method you can use self.product_id to get the Product object you want.
def clean_variations_select(self):
product = Product.object.get(id=self.product_id)
variations_select = self.cleaned_data.get("variations_select")
if variations_select == "Variation_1" and product.variation_1 == False:
raise forms.ValidationError("variation_1 was sold already")
else:
return variations_select
if "allotted_pto" (paid time off) is an integer field (expressing number of days) in a UserProfile model:
class UserProfile(models.Model):
user = models.ForeignKey(User, unique=True)
fullname = models.CharField(max_length=64, unique=False)
company = models.CharField(max_length=50, choices=CLIENT_CHOICES)
...
allotted_pto = models.IntegerField(max_length=2, blank=True, null=True)
...
User.profile = property(lambda u: UserProfile.objects.get_or_create(user=u)[0])
and "total_days" returns an integer from a vacation request model:
class LeaveRequest(models.Model):
employee = models.ForeignKey(UserProfile)
supervisor = models.ForeignKey(UserProfile, related_name='+', blank=False, null=False)
...
total_days = models.IntegerField(max_length=2, blank=True, null=True)
def __unicode__ (self):
return u'%s %s' % (self.employee, self.submit_date)
def save(self, *args, **kwargs):
fromdate = self.start_date
todate = self.return_date
daygenerator = (fromdate + timedelta(x + 1) for x in xrange((todate - fromdate).days))
self.total_days = sum(1 for day in daygenerator if day.weekday() < 5)
super(LeaveRequest, self).save(*args, **kwargs)
...
how can I construct a view that gives me the sum of "total_days" from a filter set of records and subtract that sum from the "allotted_pto" in the user profile? The simple view I wrote (see below) produces the number of "total_days" objects (in dictionary form) as opposed to counting the actual days, and the request for "allotted_pto" is apparently incorrectly constructed because it returns nothing at all...
#views.py
def leave_screen(request, id):
profile = UserProfile.objects.get(user=id)
records = LeaveRequest.objects.filter(employee=id)
agg_pto = LeaveRequest.objects.aggregate(Count('total_days'))
if profile.allotted_pto: #if the allotted_pto field in UserProfile is not empty
allotted_pto = profile.allotted_pto
remaining_pto = allotted_pto - agg_pto
else:
remaining_pto = "na"
return render_to_response("vacation/leave_request.html", {'records': records, 'agg_pto': agg_pto, 'remaining_pto': remaining_pto})
ok, figured out calculation:
def leave_screen(request, id):
...
agg_pto = LeaveRequest.objects.filter(employee=id).aggregate(Sum('total_days'))
agg_pto = agg_pto['total_days__sum']
just have to figure out how to pull the allotted_pto integer from the User Profile model.
ok, so this wasn't as difficult as I thought. The first challenge was to get an aggregate sum of objects. My first attempt was close but I should have just used "Sum" as opposed to "Count":
agg_pto = LeaveRequest.objects.filter(employee=id).aggregate(Sum('total_days'))
then I just used the python method for extracting the value from a dictionary:
agg_pto = agg_pto['total_days__sum']
finally:
def leave_screen(request, id):
user = request.user.id
profile = request.user.get_profile()
records = LeaveRequest.objects.filter(employee=id).order_by('-submit_date')
agg_pto = LeaveRequest.objects.filter(employee=id).aggregate(Sum('total_days'))
agg_pto = agg_pto['total_days__sum']
allotted_pto = profile.allotted_pto
if allotted_pto: #if the allotted_pto field in UserProfile is not empty
remaining_pto = allotted_pto - agg_pto
else:
remaining_pto = "na"
supervised_records = LeaveRequest.objects.filter(supervisor=id).order_by('-submit_date')
return render_to_response("vacation/leave_request.html", {'records': records, 'supervised_records': supervised_records, 'agg_pto': agg_pto, 'allotted_pto': allotted_pto, 'remaining_pto': remaining_pto, 'profile': profile })
I don't know why it was so hard for me to figure out the syntax for pulling objects from the UserProfile. But I do know that the django-debug-toolbar is very helpful.
I have a simple model that tracks work leave requests:
class LeaveRequest(models.Model):
employee = models.ForeignKey(UserProfile)
supervisor = models.ForeignKey(UserProfile, related_name='+', blank=False, null=False)
submit_date = models.DateField(("Date"), default=datetime.date.today)
leave_type = models.CharField(max_length=64, choices=TYPE_CHOICES)
start_date = models.DateField(("Date"))
return_date = models.DateField(("Date"))
total_days = models.IntegerField()
notes = models.TextField(max_length=1000)
def __unicode__ (self):
return u'%s %s' % (self.employee, self.submit_date)
class Admin:
pass
class Meta:
ordering = ['-submit_date']
In the view I need a function to calculate the number of days requested. Secondarily, I'll need a method to count only weekdays, but for now I've got the following:
def leave_screen(request, id):
records = LeaveRequest.objects.filter(employee=id)
total_days = LeaveRequest.return_date - LeaveRequest.start_date
tpl = 'vacation/leave_request.html'
return render_to_response(tpl, {'records': records })
which produces a attribute error
type object 'LeaveRequest' has no attribute 'return_date
any suggestions?
In total_days, you are calling the model and not the instance of that model - records - that you created.
If you want to view just a single Leave record, you would need to pass the id of the LeaveRequest
def leave_screen(request, id):
records = LeaveRequest.objects.get(id=id)
total_days = records.return_date - records.start_date
tpl = 'vacation/leave_request.html'
return render_to_response(tpl, {'records': records })
The answer that suggests using it as a property will work but I think I'll prefer keeping it as a field and just computing it at the time of insert.
class LeaveRequest(models.Model):
employee = models.ForeignKey(UserProfile)
supervisor = models.ForeignKey(UserProfile, related_name='+', blank=False, null=False)
submit_date = models.DateField(("Date"), default=datetime.date.today)
leave_type = models.CharField(max_length=64, choices=TYPE_CHOICES)
start_date = models.DateField(("Date"))
return_date = models.DateField(("Date"))
total_days = models.IntegerField()
notes = models.TextField(max_length=1000)
def __unicode__ (self):
return u'%s %s' % (self.employee, self.submit_date)
def save(self, *args, **kwargs):
self.total_days = (self.return_date - self.start_date).days
super(LeaveRequest, self).save(*args, **kwargs)
class Admin:
pass
class Meta:
ordering = ['-submit_date']
This way when you put in the logic for excluding weekends you are saving computation to calculate the days everytime at the time of listing all leave requests.
I wouldn't have 'total_days' as a field in the LeaveRequest class, but rather as a property.
class LeaveRequest(models.Model):
(other fields)
#property
def total_days(self):
oneday = datetime.timedelta(days=1)
dt = self.start_date
total_days = 0
while(dt <= self.return_date):
if not dt.isoweekday() in (6, 7):
total_days += 1
dt += oneday
return totaldays
# view function
def leave_screen(request, id):
# get leave request by id
leavereq = LeaveRequest.objects.get(id=id)
return render_to_response("vacation/leave_request.html", {"leavereq": leavereq})
# template code
...
<body>
{{ leavereq.total_days }}
</body>
I have a model that looks like this
class RSVP (models.Model):
def __unicode__(self):
return self.firstName + " " + self.lastName
firstName = models.CharField(max_length=30)
lastName = models.CharField(max_length=30)
rsvpID = models.CharField(max_length=9, unique = True)
allowedAdults = models.IntegerField(default = 2)
allowedChildren = models.IntegerField(default = 0)
adultsAttending = models.IntegerField(default = 0)
childrenAttending = models.IntegerField(default = 0)
and I have a ModelForm that looks like this
class RsvpForm(ModelForm):
class Meta:
model = RSVP
exclude= ('firstName', 'lastName', 'allowedAdults', 'allowedChildren')
What I would like to happen is that instead of a text field for the adultsAttending, a dropdown box with the values 0 to allowedAdults shows up. This is for a wedding rsvp site and I'd like to set the max number of +1's an invitee can bring on an individual basis
Any thoughts on how to go about this?
I'm thinking you want to fork the allowed children/ adults as well as the name to another model:
models.py
class Invited(models.Model):
f_name = models.CharField()
l_name = models.CharField()
allowed_adults = models.IntegerField()
allowed_children = models.IntegerField()
class RSVP(models.Model):
invited = models.ForeignKey(Invited)
adults_attending = models.IntegerField()
children_attending = models.IntegerField()
Then you would create the invited objects and assign the allowed adults and children. And the RSVP form would take those number into account when generating the choices for your drop down box.
The drop down can be implemented by overriding the IntegerField widget with a ChoiceField
forms.py
class InvitedForm(forms.ModelForm):
class Meta:
model = Invited
class RSVPForm(forms.ModelForm):
class Meta:
model = RSVP
exclude = ['invited',]
def __init__(self, *args, **kwargs):
max_adults = kwargs.pop('max_adults',2) #default to 2 if no max set
max_children = kwargs.pop('max_children',2) #default to 2 if no max set
super(RSVPForm, self).__init__(*args, **kwargs)
adult_choices = ( (x,str(x)) for x in range(max_adults+1)) )
children_choices = ( (x,str(x)) for x in range(max_children+1)) )
self.fields['adults_attending'] = forms.ChoiceField(choices = adult_choices)
self.fields['children_attending'] = forms.ChoiceField(choices = children_choices)
views.py
def rsvp_view(request, invited_id):
invited = get_object_or_404(Invited, pk=invited_id)
if request.method=='POST':
form = RSVPForm(request.POST, max_adults=invited.allowed_adults,
max_children=invited.allowed_children)
if form.is_valid():
rsvp = form.save(commit=False)
rsvp.invited = invited
rsvp.save()
return HttpResponse("Success")
else:
form = RSVPForm(max_adults=invited.allowed_adults, max_children=invited.allowed_children)
context = { 'form':form,
'invited':invited }
return render_to_response('rsvp.html', context,
context_instance=RequestContext(request))