django class-based views key word - django

I've been following the manual for generic views for Django 1.4, but can get the 'list books by publisher' example to work. My site is slightly different in that I'm trying to list bookings of a property by the name (or id) of the person who books the property. People will book more than once, so I want to be able to see what their bookings were.
My views.url for this is:
class GuestBookingListView(DetailView):
context_object_name = 'guest_booking'
template_name = 'guest_booking.html'
def get_queryset(self):
self.guest = get_object_or_404(Guest)
return Booking.objects.filter(guest = self.guest)
def get_context_data(self, **kwargs):
context = super(GuestBookingListView, self).get_context_data(**kwargs)
context['guest'] = self.guest
return context
My model is:
class Guest(models.Model):
first_name = models.CharField(max_length=30)
last_name = models.CharField(max_length=50)
spouse_first = models.CharField(max_length=30, blank=True)
spouse_last = models.CharField(max_length=50, blank=True)
num_child = models.IntegerField(verbose_name='Number of children')
address = models.TextField(max_length=50, blank=True)
city = models.CharField(max_length=60, blank=True, verbose_name='Town / City')
state_province = models.CharField(max_length=30, blank=True, verbose_name='County')
post_code = models.CharField(max_length=8, blank=True)
country = models.CharField(max_length=50, blank=True)
email = models.EmailField(blank=True)
landline = models.CharField(max_length=25, blank=True)
mobile = models.CharField(max_length=25, blank=True)
def __unicode__(self):
return u'%s %s' % (self.first_name, self.last_name)
class Booking(models.Model):
guest = models.ForeignKey(Guest)
ack_date = models.DateField(verbose_name='Date acknowledged')
start_date = models.DateField(verbose_name='Start date')
end_date = models.DateField(verbose_name='End date')
dep_recd = models.DateField(null=True, blank=True, verbose_name='Deposit received')
bal_recd = models.DateField(null=True, blank=True, verbose_name='Balance received')
keys_sent = models.DateField(null=True, blank=True, verbose_name='Date keys sent')
sec_retn = models.DateField(null=True, blank=True, verbose_name='Security deposit returned')
rtm_sent = models.IntegerField('Status', blank=True)
notes = models.TextField(blank=True, verbose_name='Notes')
and my urls.py is:
url(r'^guests/(?P<pk>\d+)/$', GuestBookingListView.as_view (
#context_object_name = 'booking_list',
)),
So far as I can see this identical (with different field names) to the example, but the result I get is:
get() returned more than one Guest -- it returned 26! Lookup parameters were {}
The 'get' is retrieving all of the Guests in the database, not the one which I've selected.
I've spent hours of searching and experimenting on this, but to no avail. If I put 'guest = 11' it works, so there's something wrong with the pk.
Thank you!

You haven't given any sort of criteria to get the guest. You've just said, in effect, "give me guest", and Django has given you all 26 of them. If you want to filter by the pk kwarg, you should say so:
self.guest = get_object_or_404(Guest, pk=self.kwargs['pk'])

Related

Error for my model with ManyToManyField in Django

I am working for a personal project that is using an API and having user authentication with JWT (but used in serializer). I wanted to implement ManyToManyField for user and city but it doesn't work properly. This is the extended model I have found and django aggregation . I want that the UserSearchLocation to store the City and when logged in to see the city, while other users will not see it until the search same city.
models.py
class UserSearchLocation(models.Model):
city_name = models.CharField(max_length=85, blank=False)
def __str__(self):
return self.city_name
class City(models.Model):
user_searched_locations = models.ManyToManyField(User,
through='UsersLocations',
through_fields=('city', 'user'),
related_name="my_cities",
blank=True)
id = models.AutoField(primary_key=True, editable=False)
location = models.CharField(max_length=85)
country = models.CharField(max_length=85, blank=True)
country_code = models.CharField(max_length=2, blank=True)
latitude = models.DecimalField(max_digits=6, decimal_places=4,
null=True, blank=True)
longitude = models.DecimalField(max_digits=6, decimal_places=4,
null=True, blank=True)
zip_code = models.PositiveIntegerField(default=0)
#users_location = models.ManyToManyField(UserSearchLocation)
def __str__(self):
return f'{self.location}, {self.country_code}'
def save(self, *args, **kwargs):
self.location = self.location.capitalize()
self.country = self.country.capitalize()
self.country_code = self.country_code.capitalize()
return super(City, self).save(*args, **kwargs)
class Meta:
verbose_name_plural = 'cities'
unique_together = ("location", "country_code")
class UsersLocations(models.Model):
id = models.AutoField(primary_key=True, editable=False)
user = models.ForeignKey(User, on_delete=models.CASCADE, null=True)
city = models.ForeignKey(City,
on_delete=models.CASCADE,
related_name='locations_by_users',
null=True)
To add in localhost/admin/ a City works, but when to add a UserSearchLocation I have this error:
Exception Value:
column base_usersearchlocation.user_id does not exist
LINE 1: SELECT "base_usersearchlocation"."user_id", "base_usersearch...
Your error says the city.location doesn't exist - location is a CharField on your City model - are you sure you've run migrations and don't have any naming conflicts?

Django Admin, show inline based on slug

Have the following models
class FootballWebsite(models.Model):
"""Football service website."""
url = models.URLField, unique=True)
#football service
id = models.CharField(primary_key=True,
#is this domain blocked
blocked = models.BooleanField(default=False)
#is it online or offline
online = models.BooleanField(default=False)
updated = models.DateTimeField(auto_now=True, auto_now_add=True)
sub_categories = models.ForeignKey(SubCategory, default=1)
referral = models.TextField(blank=True)
mirror = models.ForeignKey('FootballWebsite', blank=True, null=True)
rank = models.PositiveIntegerField(default=0, blank=True, null=True)
screenshot = models.BooleanField(default=False)
class Meta:
"""Meta class."""
app_label = 'ahmia'
def __unicode__(self):
return u'%s' % (self.url)
"""The datetime when the football service was last seen online"""
try:
return self.footballwebsitestatus_set.filter(online=True).latest('time').time
except FootballWebsiteStatus.DoesNotExist:
return None
class FootballWebsiteDescription(models.Model):
"""Football service website description."""
about = models.ForeignKey(Footballebsite)
title = models.TextField(blank=True, null=True)
keywords = models.TextField(blank=True, null=True)
description = models.TextField(blank=True, null=True)
relation = models.URLField(blank=True, null=True)
subject = models.TextField(blank=True, null=True)
type = models.TextField(blank=True, null=True)
updated = models.DateTimeField(auto_now=True, auto_now_add=True)
language = models.TextField(null=True, blank=True)
contactInformation = models.TextField(null=True, blank=True)
officialInfo = models.BooleanField(default=False)
slug = AutoSlugField(populate_from=['title'], allow_duplicates=True, null=True)
class Meta:
"""Meta class."""
app_label = 'ahmia'
def __unicode__(self):
return unicode(self.about.url)
def save(self, *args, **kwargs):
self.slug = slugify(self.title)
super(FootballebsiteDescription, self).save(*args, **kwargs)
def __unicode__(self):
return u'%s' % (self.title)
I have a huge amount of links, and i would like to bulk assign them into a category or mark them as blocked based on identical title slug.
Managed to at least get a list of title_slugs with the code below, but the following step, i would like to get an inline list with all sites that have an identical title_slug and bulk assign those all in their a category
class FootballWebsiteInline(admin.TabularInline):
model = FootballWebsite
class FootballWebsiteDescriptionAdmin(admin.ModelAdmin):
list_display = ['show_slug']
def show_slug(self, obj):
return format_html("<a href='{url}'>{url}</a>", url=obj.slug)
inlines = [
FootballWebsiteInline,
]
Above code obviously doesn' t work, since the title slug which can appear many times is not a primary key.
Is it possible to get an inline list based on the title slug in this case which is not a primary key at all, or am i going about this the wrong way?
When possible at all, some further tweaking would be to group the identical title slugs

Showing data related to a logged in user in Django

I am building this simple system for a school, where students can log in to see their results at the end of every semester. I designed a model for exams with a manytomany relationship to a user. My problems is in my template am finding it hard to show a exams results related to a logged in user.
models.py
class StudentProfile(models.Model):
SEX_CHOICES = (
('Male', 'Male'),
('Female', 'Female')
)
user = models.OneToOneField(User, on_delete=models.CASCADE)
other_name = models.CharField(max_length=30, null=True, blank=True)
birth_of_date = models.DateField(null=True, blank=True)
birth_Of_admission = models.DateField(null=True, blank=True)
nationality = models.CharField(max_length=120)
phone_number = models.CharField(max_length=15, validators=[MinLengthValidator(10)])
gender = models.CharField(max_length=120, choices=SEX_CHOICES)
home_address = models.CharField(max_length=250, null=True, blank=True, )
passport_picture = models.ImageField(upload_to='passport_picture', null=True, blank=True,
help_text='Upload the passport picture here')
def __str__(self):
return "%s %s" % (self.user.first_name, self.user.last_name)
#receiver(post_save, sender=User)
def create_or_update_user_profile(sender, instance, created, **kwargs):
if created:
StudentProfile.objects.create(user=instance)
instance.studentprofile.save()
class Subject(models.Model):
subject_name = models.CharField(max_length=30, null=True, blank=True)
def __str__(self):
return self.subject_name
class Year(models.Model):
year = models.CharField(max_length=30, null=True, blank=True)
def __str__(self):
return self.year
class Exam(models.Model):
TERM_CHOICES = (
('First Term', 'First Term'),
('Second Term', 'Second Term'),
('Third Term', 'Third Term')
)
level = models.ForeignKey('Level', null=True, blank=True, on_delete=models.CASCADE)
student = models.ForeignKey(Year, null=True, blank=True, on_delete=models.CASCADE)
year = models.ForeignKey(Year, null=True, blank=True, on_delete=models.CASCADE)
subject = models.ForeignKey(Subject, null=True, blank=True, on_delete=models.CASCADE)
term = models.CharField(max_length=120, default="", choices=TERM_CHOICES)
mid_term_score = models.PositiveSmallIntegerField(help_text='the marks scored for mid term exams')
End_of_term_score = models.PositiveSmallIntegerField(help_text='the marks scored for end of term exams')
class_work_score = models.PositiveSmallIntegerField(help_text='the marks scored for class work')
def __str__(self):
return self.subject + "-" + self.term
views.py
class StudentView(LoginRequiredMixin, ListView):
model = Exam
template_name = 'student.html'
context_object_name = 'student'
def get_object(self):
return self.request.user.exam
What I am trying to do is to show logged in student only his results based on the exams he has taken and but is rather showing me all. Even those he has not taken.
you can retrive those exams by set_all look_up_relationship or manually can query on Exam model.
possible way can be like this
def get_object(self):
return self.request.user.exam_set.all()
Also you can try this
def get_object(self):
return Exam.objects.filter(student_id=self.request.user.id)
Edit
If i understand you properly now, then student's current level is an important factor of this Exam filtering. We should add that too than, otherwise all exam will appear. But from your Exam model structure, i haven't see any level entity associated with User model present. I am assuming term and level actually same thing ( most likely which are not )
def get_object(self):
return Exam.objects.filter(student_id=self.request.user.id, term = self.request.user.level )

Update existing M2M relationship in Django

I'm trying to save an existing instance of a customer record. Its model has a M2M to the vehicle model (since a customer can multiple vehicles). After reading several questions/answer here, I still do not know how to solve this.
Customer model:
class Customer(models.Model):
vehicle_id = models.ManyToManyField(VehicleSale)
name = models.CharField(max_length=40, blank=True, db_index=True, null=True,
verbose_name='name')
lic = models.CharField(max_length=20, blank=True, db_index=True, null=True,
verbose_name='license')
addr = models.CharField(max_length=40, blank=True, null=True, verbose_name='address')
city = models.CharField(max_length=15, blank=True, null=True, verbose_name='city')
state = models.CharField(max_length=2, blank=True, null=True, verbose_name='state')
zip = models.CharField(max_length=10, blank=True, null=True, verbose_name='zipcode')
email = models.EmailField(blank=True, null=True, verbose_name='email')
tel1 = models.CharField(max_length=15, blank=True, verbose_name='Tel. 1', null=True)
tel2 = models.CharField(max_length=15, blank=True, verbose_name='Tel. 2', null=True)
ssn = models.CharField(max_length=12, blank=True, db_index=True, null=True,verbose_name='SSN')
class Meta:
db_table = 'customer'
def __unicode__(self):
return self.name
def save(self, *args, **kwargs):
self.name = self.name.upper()
self.addr = self.addr.upper()
self.city = self.city.upper()
self.state = self.state.upper()
return super(Customer, self).save(*args, **kwargs)
In the view, after defining customer as
customer = current_vehicle.customer_set.all()
I tried the following:
if 'customer' in request.POST:
if customer:
customer_form = CustomerForm(request.POST, instance=customer[0])
if customer_form.is_valid():
customer_form.save()
Also tried adding before customer_form is defined:
customer.vehicle_id = current_vehicle.id
And then this after the form:
customer_form.vehicle_id = current_vehicle.id
Form is not valid so it's not saved. Upon checking {{ form.errors}}, it always reports vehicle_id is required.
Finally, after the answer in this, I adjusted it to my scenario by adding:
obj = customer_form.save(commit=False)
and hoping to assign vehicle_id, but it fails immediately.
What am I missing?
Thanks.
1st EDIT:
The section on the view now looks as:
customer_form = CustomerForm(request.POST, instance=customer[0])
customer_form.save()
customer_form.vehicle_id.add(current_vehicle)
You are misunderstanding what a ManyToMany field is here:
customer_form.vehicle_id = current_vehicle.id
vehicle_id is defined as a ManyToMany field on your Customer model, therefore you can't just assign a single id to it. You have to add an instance of VehicleSale model, eg:
customer_form.vehicle_id.add(current_vehicle)
See docs here:
https://docs.djangoproject.com/en/dev/topics/db/examples/many_to_many/
See also this answer for why you can't save until you populate the vehicle_id relation:
https://stackoverflow.com/a/2529875/202168

Django-tables2 reverse lookup

I have a table that displays a list of "leads" which are rendered fine. There is also a related model which is called "Leadupdate" that is related to "lead" model that is used in the table. There is a many to one relationship from Leadupdate to lead with a foreign key. I want to display all the related updates for the individual "leads" in one of the updates column. There are several examples online for following forward relationship through foreign key but haven't found one for reverse yet. Here is one example of said relationship Accessor forward look up.
EDIT: Look up will be done on a Django-tables2 module instance table. I am not asking reverse look up on a model but doing it in context of Django-tables2.
Models.py:
class lead(models.Model):
slug = models.SlugField(unique=True,blank=True, null=True)
first_name = models.CharField(max_length=100)
last_name = models.CharField(max_length=100, blank=True, null=True)
business_name = models.CharField(max_length=100,blank=True, null=True)
email = models.EmailField(max_length=75, blank=True, null=True)
phone_number = models.CharField(max_length=20, blank=True, null=True)
address = models.CharField(max_length=150, blank=True, null=True)
city = models.CharField(max_length=50, blank=True, null=True)
state = models.CharField(max_length=10, blank=True, null=True)
zipcode = models.CharField(max_length=5, blank=True, null=True)
submission_date = models.DateTimeField(auto_now_add=True, blank=True)
assigned_to = models.ManyToManyField(Listing,blank=True, null=True, related_name="leads")
requested_software = models.CharField(max_length=50, blank=True, null=True)
type_of_business = models.CharField(max_length=30, choices=TYPE_OF_BUSINESS, default='Bar', blank=True, null=True)
time_frame = models.CharField(max_length=10, choices=TIME_FRAME, default='1')
comments = models.TextField(blank=True, null=True)
def __unicode__(self):
return self.business_name
#models.permalink
def get_absolute_url(self):
return('listing_detail', (),{'slug' :self.slug,})
def save(self, *args, **kwargs):
if not self.slug:
self.slug = slugify(self.business_name)
super(lead, self).save(*args, **kwargs)
class Leadupdate(models.Model):
CONFIDENCE_LEVEL = (
('HOT', 'HOT'),
('COLD', 'COLD'),
)
LEAD_VALUE = (
('1K3K', '1K-3K'),
('5K10K', '5K-10K'),
('10K20K', '10K-20K'),
('20K50K', '20K-50K'),
('50KUP', '5OK-UP'),
)
ESTIMATED_CLOSING = (
('1w4w', '1-4 Weeks'),
('1m3m', '1-3 Months'),
('3m6m', '3-6 Months'),
('6m+', '6+ Months'),
)
updatedate = models.DateTimeField(auto_now_add=True)
update = models.TextField(blank=True, null=True)
updatefrom = models.ForeignKey(Listing, related_name="update_from", blank=True, null=True)
lead = models.ForeignKey(lead, related_name="related_update",blank=True, null=True)
lead_confidence_level = models.CharField(max_length=10, choices=CONFIDENCE_LEVEL, default='COLD', blank=True, null=True)
estimated_lead_value = models.CharField(max_length=10, choices=LEAD_VALUE, default='1K3K', blank=True, null=True)
estimated_closing_frame = models.CharField(max_length=10, choices=ESTIMATED_CLOSING, default='1-4 Weeks', blank=True, null=True)
def __unicode__(self):
return u" %s - %s " % (self.update, self.updatedate)
Table:
class LeadTable(tables.Table):
business_name = tables.LinkColumn('lead-detail', args=[A('slug')])
updates = tables.Column(accessor='lead.related_update')
class Meta:
model = lead
fields = ("business_name","first_name", "last_name","number_of_pos","submission_date","updates")
attrs = {"class":"paleblue"}
A late answer, but here is what works for me in Django 1.8.6 with django-tables2 1.1.0 (based on Django-Tables2 Issue 156 and This answer). To access a one to many set of objects via a foreign key relation you need to just use the related_name in the accessor and then create a render method to produce what gets written to column cell. In that method you can then get all the foreign model objects and access their fields in a for loop.
class LeadTable(tables.Table):
business_name = tables.LinkColumn('lead-detail', args=[A('slug')])
updates = tables.Column(accessor='related_update')
def render_updates(self, value, table):
updates = ""
uFirst = True
updatesList = list(value.all())
for u in updatesList:
if not uFirst:
updates += ", "
else:
uFirst = False
updates += u.update
return updates
class Meta:
model = lead
fields = ("business_name","first_name", "last_name","number_of_pos","submission_date","updates")
attrs = {"class":"paleblue"}
according to django docs
in your views you can access them in this way (assuming lead_instance is an instance of lead class):
all_leadtables_for_lead = lead_instance.leadtable_set
a side note: use Capitalized names for classes (class Lead(models.Model):) in order to adhere to python PEP8 guidelines.