Automatically populate relations in Django admin - python

I'm working on my first Django app. My goal is to have two models, one for offices and one for employees, and when a person record is created (in the admin site), creating and specifying the room also populates that room with that person.
I was able to create the models, but now I'm stuck in a catch-22 where when I add a person, I have to create a room, but to create a room I have to add a person, etc...
How can I create and automatically populate a room like this?
Here is the relevant code from models.py:
class Room(models.Model):
number = models.CharField('Room number', primary_key=True, max_length=50)
occupant = models.ManyToManyField('Person', blank=True) # Can have multiple occupants
class Person(models.Model):
name = models.CharField('Full name', max_length=200)
office = models.ForeignKey(Room, on_delete=models.SET_NULL, null=True) # Some offices may not have an occupant
Update: I added blank=True to office so I can create an office with no occupant. But, even when I add a person and assign their office to that number, and it shows that in the admin page, the detail-view page doesn't seem to grab that, unless I manually go into the Room admin page and select the person. Can that part be automated?

Related

Djnago how to split users and customres

In my project (small online shop) I need to split registration for users and customers.
So the information what I found when somebody registered in django then his account stored in one table, in this table I can see admin user and staff and another registered accounts, and I can sse them all in admin on Users page. But I do not want ot put all accounts in one "basket". I need split them fro different tables.
For example superuser can create in admin area a new user (content manager) and provide him access/permission to manage admin area (create product etc.) - this users and super user will be on default User page. On the page Customers will be displaying only users who registered for example via https://mysite/account/register page, after registration this customer account I can see in Customers page in the admin area but not in Users page. And this customer can login to his account for example via https://mysite/account/login
Is this possible?
As Jay said, everyone registered in the database is still a User whatever their role may be (admin, superuser, customer). What you could do is create a Profile model where everyone will have their information such as telephone, location etc, and you will also add another field clarifying their property.
PACKAGES = [
('customer', 'Customer'),
('support', 'Support'),
('admin', 'Admin'),
]
class Profile(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE, primary_key=True)
image = models.ImageField(default='user_avatar.png', upload_to='...')
last_visit = models.DateField(default=timezone.now, blank=True)
location = models.CharField(max_length=254, null=True, blank=True)
contact_phone = models.CharField(max_length=15)
user_role = models.CharField(default="customer", choices=PACKAGES, max_length=20)
Then all you need to do is edit your admin.py to implement a search parameter there:
class ProfileAdmin(admin.ModelAdmin):
list_filter=('user_role',)
admin.site.register(Profile, ProfileAdmin)
Doing that will give you a filter_list in the right corner of your admin page but that is for admin page only.
If you want to access different roles in your views or your templates you will do so by getting the user_role you need:
customers = Profile.objects.filter(user_role='customer')

Listing all movies of a specific cinema - Foreign Key Django

I am new to Django and I have a question regarding the models and foreignkeys.
I have two models: Cinema and Movie.
One Cinema can have multiple movies, so I placed the foreign key of cinema in the Movie model.
class Cinema(models.Model):
name = models.CharField(max_length=255)
address = models.CharField(max_length=255)
class Movie(models.Model):
title = models.CharField(max_length=255)
description = models.CharField(max_length=255)
posting_cinema = models.ForeignKey('cinemas.Cinema', on_delete=models.CASCADE, null=True)
Now I want to list all the movies of a specific Cinema.
How can I do it?
The idea is the following:
The user clicks on a cinema, it opens a page with the cinema details and a button "see movies". If the user clicks this button, a new page opens and I want to have listed there the movies of that specific cinema.
I tried to figured out some solutions but sadly I am stuck. I was thinking about Movie.objects.filter(#something) but I am not sure
For a given Cinema you can use:
some_cinema.movie_set.all()
Or you can give the ForeignKey a more sensical name to query in reverse:
class Movie(models.Model):
title = models.CharField(max_length=255)
description = models.CharField(max_length=255)
posting_cinema = models.ForeignKey(
'cinemas.Cinema',
on_delete=models.CASCADE,
null=True,
# here we give the reverse relation a name
related_name='movies'
)
then you can query this with:
some_cinema.movies.all()
An alternative is to filter based on the ForeignKey, for example:
Movie.objects.filter(posting_cinema=some_cinema)
or if you have the primary key of the cinema:
Movie.objects.filter(posting_cinema__pk=some_cinema_pk)
(this can for example save a fetch of the Cinema object, if you never really need the Cinema itself).

Problems with TabularInline in Django Admin

I'm porting an Access application to Python/Django. There is a SchoolInfo table and a Campuses table with a foreign key pointing to the SchoolInfo table. In Access, I have a Campuses subform (continuous) embedded into the SchoolInfo form with match fields defined properly pointing to School_ID. So for School 1 I only show campuses for that school.
In Django, I added the SchoolInfo table to Admin and am trying to replicate the Access UI using TabularInline. Here are snippets of model and admin:
class Schoolinfo(models.Model):
school_id = models.AutoField(db_column='School_ID', primary_key=True) # Field name made lowercase.
schoolcode = models.CharField(db_column='SchoolCode', max_length=10) # Field name made lowercase.
schoolname = models.CharField(db_column='SchoolName', max_length=50, blank=True, null=True) # Field name made lowercase.
class Campuses(models.Model):
campus_id = models.AutoField(db_column='Campus_ID', primary_key=True) # Field name made lowercase.
campusno = models.IntegerField(db_column='CampusNo', default=1) # Field name made lowercase.
schoolcode = models.CharField(db_column='SchoolCode', max_length=10) # Field name made lowercase.
school = models.ForeignKey('Schoolinfo', models.DO_NOTHING, db_column='School_ID', unique=True) # Field name made lowercase.# school = models.IntegerField(db_column='School_ID') # Field name made lowercase.
campusname = models.CharField(db_column='CampusName', max_length=15, blank=True, null=True) # Field name made lowercase.
class CampusesInline(admin.TabularInline):
model = Campuses
admin.site.register(Campuses)
class SchoolInfoAdmin(admin.ModelAdmin):
fields = (
('schoolcode', 'schoolname'), ('contactname', 'contacttitle'), ('contactphone', 'contactemail'),
('clockhoursschool', 'schoolsendsawardletters'), ('tin_no', 'duns_no'), ('pell_id', 'ope_id'))
save_on_top = True
inlines = [CampusesInline,]
admin.site.register(Schoolinfo, SchoolInfoAdmin)
When I select a school for edit, it properly shows the school fields, then the TabularInline for campuses, but here is the problem:
There are multiple schools in the database, each having 1 or more campuses. The TabularInline properly shows the campus or campuses for the active school, but it also has several blank records (which I assume are related to the campus records for other schools).
If I add "unique=True" to the foreign key (as shown in the model above), the blank records disappear and all looks good. Unfortunately, I also loos the link at the bottom of the inline to add a new campus.
I'm VERY new to Python/Django, so can't figure out how to fix this. I suppose my choices are some type of filtering in the inline (and take out the unique=True from the model), or leave that in and figure out how to restore the "add" link to the inline.
Are there any suggestions on how to fix this?
Thanks...
but it also has several blank records (which I assume are related to
the campus records for other schools).
Those "blank" records are for adding new campuses to the school. You can use the "extra" attribute on your CampusInline to control the number of blank lines.
If I add "unique=True" to the foreign key (as shown in the model
above), the blank records disappear and all looks good. Unfortunately,
I also loos the link at the bottom of the inline to add a new campus.
If you add "unique" to the "school" field, that would mean that a school could only appear once in the campus table. Which doesn't (usually) make much sense for a foreign key.

Tricky logic to calculate unique recent visitors in a Django app

I have a live web-based chat app made in Django. Users can form groups where other users can congregate, leave messages (called replies) and photos. The url every user visits to access a group is:
url(r'^group/(?P<pk>\d+)/reply/$', auth(GroupView.as_view()), name="group_reply"),
where pk is group.pk.
My question is: how can I get a list (or set) of all distinct users who accessed a certain group's URL in the last 5 mins? Essentially, I'm trying to calculate the number of unique recent visitors for each group. I can't seem to wrap my head around how to do this, though I guess sessions information could help? (I'm using django user_sessions in this project, which
"makes session objects a first class citizen like other ORM objects"
).
In case required, the model behind a group is:
class Group(models.Model):
topic = models.TextField(validators=[MaxLengthValidator(200)], null=True)
rules = models.TextField(validators=[MaxLengthValidator(500)], null=True)
owner = models.ForeignKey(User)
private = models.CharField(max_length=50, default=0)
category = models.CharField(choices=TYPE, default=1, max_length=25)
created_at = models.DateTimeField(auto_now_add=True)
And the model behind posting a reply in each group is:
class Reply(models.Model):
text = models.TextField(validators=[MaxLengthValidator(500)])
which_group = models.ForeignKey(Group)
writer = models.ForeignKey(User)
submitted_on = models.DateTimeField(auto_now_add=True)
image = models.ImageField(upload_to=upload_pic_to_location, null=True, blank=True )
And User is a vanilla django.contrib.auth user.
You don't have anything that is collecting the data you need. If you want to record visits to a page, you will need to build a model to do that; a simple one with FKs to User (for the visitor) and Group (for the group being visited), plus a timestamp, should be enough. Then your GroupView can make an entry in that table every time a user visits.

Simplest way for users to add themselves to a "team" in Django

from django.contrib.auth.models import User
from django.db import models
class Team(models.Model):
team_name = models.CharField(max_length=255, unique=True) ## they can create a new team here
description = models.TextField()
slug = models.SlugField(unique=True)
user = models.OneToOneField(User, blank=True, null=True) ## I connect my User here, so they can "own" this info...
Users have the option to create a new team (via the 'team_name' field), but I also want to give users the option to join another team (created by a different user), can I just add a new field to my Team model? And preferably, on the form, they could see a list of created teams, check the one they want to join and save the form.
Could I add something like this to my Team class:
team = forms.ModelMultipleChoiceField(queryset=Team.objects.all()).filter('team_name')
or maybe something like:
TEAM_CHOICES = Team.objects.all()).filter('team_name')
team = forms.CharField(widget=forms.Select(choices=TEAM_CHOICES))
And, how would that data be saved correctly?
If you wanted to allow users to join a team, I'd have a team attribute on the user model that was a FK to the Team.
Then in a form, you could define the list of available teams as you've suggested;
team = forms.ModelMultipleChoiceField(queryset=Team.objects.all())
And I'd also suggest looking at Select2 which creates a javascript 'search' type field that will filter the teams when someone starts to type characters.
Furthermore, the user field in your Team model would be better named as creator or owner so that you don't confuse them with a standard user associated with the team.

Categories