So, I have the following models:
class Band(models.Model):
name = models.CharField(max_length=50)
class Contract(models.Model):
band = models.ForeignKey(Band)
when = models.DateTimeField(auto_now_add=True)
salary = models.IntegerField()
class Musician(models.Model):
first_name = models.CharField(max_length=50)
last_name = models.CharField(max_length=50)
instrument = models.CharField(max_length=100)
bands = models.ManyToManyField(Band, through=Contract)
class Album(models.Model):
artist = models.ForeignKey(Musician)
name = models.CharField(max_length=100)
release_date = models.DateField()
num_stars = models.IntegerField()
So, I wanted to expose that on the admin page. So far, so good.
Note that our musicians here keep jumping in and out from bands. Some say one of them even had been on over 2 millions bands in his life-time. I don't know, maybe the bands are Whitesnake, Metallica or something.
How should we do that on the Django Admin Page?
I tried using raw_id_fields and apart the fact I didn't like the effect, it didn't work so well. It took a lot of time to load and it didn't let me add more ids. Weird.
I've used admin.StackedInline with no luck cause it will try to load every contract in a which, well, it's gonna take only 2 thousand years.
When Musician had a direct relation to Band it worked just fine with this library. But now that the relation isn't an straight one. Looks like autocomplete doesn't support it(it was getting slow anyway).
So, with all of this, I ask you lord SO members. What's the best way to do this? Is it autocomplete? Someone must have had to come across this issue!
Thanks in advance.
To avoid loading every bands in your admin page use autocomplete_fields Django doc.
Just use it like that in your admin.py.
autocomplete_fields = ('bands',)
Then no bands will be pulled from DB to front, but you will be able to select it through a Select2 search field and it will be printed as "tags".
I found this solution and hope it will help somebody in the same situation:
I have many to many relations between the Product and Characteristic model.
So, in the admin.py I am setting a form for a Product like the following where catch/get all the Characteristics and make the "prefecth_related" for Characteristic, as well the "select_related" could be done there:
class ProductAdminForm(forms.ModelForm):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.fields['characteristics'].queryset = Characteristic.objects.prefetch_related('category').all()
Related
the idea is that students can send a ping to their teacher if they do not understand something, but first I am trying to get the student, teacher and whatever class they are in relationship
so in my models after a few attempts I have come up with this
Models
from django.db import models
class Student(models.Model):
name = models.CharField(max_length=50)
class Teacher(models.Model):
name = models.CharField(max_length = 70)
class Lecture(models.Model):
name = models.CharField(max_length = 70)
members = models.ManyToManyField(
Student,
through = 'part_of_class',
through_fields = ('lecture', 'student'),
)
lecturers = models.ManyToManyField(
Teacher,
through = 'Teacher_of_class',
through_fields = ('lecture', 'teacher'),
)
class Teacher_of_class(models.Model):
lecture = models.ForeignKey(Lecture)
teacher = models.ForeignKey(Teacher)
class part_of_class(models.Model):
lecture = models.ForeignKey(Lecture)
student = models.ForeignKey(Student)
Question is adding a student field messes up, and Im not even sure this is the right way, it sounds right in my head but I am sure I am missing something, any clues?
I'm not entirely sure that you need explicit intermediary relationships (Teacher_of_class and part_of_class). Instead, you should try utilizing fields within the other models to do what you want. For example, will a lecture generally have more than one teacher, or just one? You could model either of those with a field in Lecture.
Edit: Apologies, I misread your code initially with regards to the fields. My suggestion is to not use an additional relationship class unless you know why you need it.
If you just want to have a lecture that can have multiple students and multiple lecturers, you do not need to have the intermediate models, Django will handle this for you if you don't specify any. I would only use the intermediate tables if you wanted to store something with that relationship.
Also when trying to add your student and teacher objects to the lecture model, be sure to save them.
Your save code should look something like this:
aStudent = Student(name="Taco")
aTeacher = Teacher(name="Burrito")
aStudent.save()
aTeacher.save()
aLecture = Lecture(name="Cooking With Python!")
aLecture.members.add(aStudent)
aLecture.lecturers.add(aTeacher)
aLecture.save()
Hope this helps!
I have two models:
class Account(models.Model):
...
class Transaction(models.Model):
....
account = models.ForeignKey(Account)
source_account = models.ForeignKey(Account, null=True)
I need to display the number of transactions for each of a user's accounts. Django's annotate seemed like the proper tool for this task. I did:
queryset = models.Account.objects.filter(user=self.request.user)
queryset.annotate(transactions_count=Count('transaction'))
This gives the correct number for transactions with account field set to the predicate account but leaves out transactions where source_account is set to the predicate account.
Using the Django shell I am able to do something like:
accounts_count = user_transactions.filter(Q(account=account)|Q(source_account=account)).count()
This gives the correct answer. Is there something I am doing wrong? Can someone point me in the correct direction. Any assistance is highly appreciated.
I would set related_name to your ForeignKey fields. Then it's a bit easier to work with them. So for example in your models let's set:
class Transaction(models.Model):
...
account = models.ForeignKey(Account, related_name='transactions')
source_account = models.ForeignKey(Account, null=True, related_name='source_transactions')
then can do something like:
queryset = models.Account.objects.filter(user=self.request.user).annotate(transactions_count=(Count('transactions')+Count('source_transactions'))
it would work without the naming too, it's just more readable and easier. The main point is adding the two Count as one field in annotate.
The best approach for these types of problems is to imagine them in raw SQL and then try to mimic it in Django ORM.
(in raw sql you would also simply just add two columns like SELECT (a.col + a.col2) AS count
The problem is that your transaction has to ForgeinKeys to Account. I would suggest trying something like this
class Transaction(models.Model):
....
account = models.ForeignKey(Account, related_name="transaction_account")
source_account = models.ForeignKey(Account, null=True, related_name="transaction_source_account")
Then in your query:
queryset.annotate(transactions_count=((Count('transaction_account') + Count('transaction_source_account'))
Assume some Company with Employees. There are Name and Contact information bound to each Employee. Each Contact contains Street and Phones fields.
What I want is a page which lists employees within a company. But everything must be listed as forms. Because I want to be able to modify the particular Employee information and the most important - I want to be able to add new Employees (clicking a button "Add new employee" must add a new empty "Employee form"). As well as it must allow to add a new phone number to the existing Employee's Contact information any time.
The data model looks like:
--Company
----Employee1
------Name
------Contact
--------Street
--------Phones
----------Phone1
----------Phone2
----Employee2
------Name
------Contact
--------Street
--------Phones
----------Phone1
----------Phone2
----------Phone3
...
Could someone please help to design Models and Forms for such a task? Your help is very much appreciated. Many thanks!
P.S. Forgot to mention that I want all the data "collected" in the Company object at the end of the day. I mean when I serialize c = Comapany.objects.all()[0] on the back end the entire employee information must be visible, like c.employees[0].contact.phones[0] must be the first employee's first phone number. Thanks.
P.P.S.
That is not the case that I'm just forwarding my project. This is just an hypothetical example I'd created to present the problem. I'm a django newbie and trying to understand how the framework gets things rolling.
I've spent lot of time on this. I've found several ways to go, but no one got me to the end. For instance, a wonderful blog about nested formsets http://yergler.net/blog/2013/09/03/nested-formsets-redux/ helped with forms and rendering. But, it solved only the half of the problem. The data like I mentioned above is not "being collected" into an object. At the end of the day I want to serialize a Company object and save it in yaml format using pyyaml (see my previous post django: want to have a form for dynamically changed sequence data).
Django is perfect with "static" models and forms, ModelForms are awesome. But what if your model needs to be changed dynamically? No standard way to go. Either no appropriate documentation nor I could find a one. Thus, I'd like to hear how experts imagine the solution for such a problem.
Try this:
from django.db import models
class _Contact(object):
pass
class Company(models.Model):
name = models.CharField(max_length=255)
created_at = models.DateTimeField(auto_now_add=True)
#property
def employees(self):
return self.employee_set.prefetch_related('phones').order_by('-created_at')
class Phone(models.Model):
number = models.CharField(max_length=255)
created_at = models.DateTimeField(auto_now_add=True)
class Employee(models.Model):
name = models.CharField(max_length=255)
street = models.CharField(max_length=255)
phones = models.ManyToManyField('Phone', through='EmployeePhone', blank=True)
created_at = models.DateTimeField(auto_now_add=True)
company = models.ForeignKey(Company)
#property
def contact(self):
_contact = _Contact()
_contact.street = self.street
_contact.phones = self.phones.order_by('-employeephone__created_at')
return _contact
class EmployeePhone(models.Model):
employee = models.ForeignKey(Employee)
phone = models.ForeignKey(Phone)
created_at = models.DateTimeField(auto_now_add=True)
However, you should just use employee.street and employee.phones. employee.contact is redundant.
I'm trying to wrap my head around how I would structure my database tables in the Django webapp I'm writing. I'm a relative newbie to web development, but this is the very first time I've tried to use a database, so bear with me if it's a stupid question.
The webapp goes through each Oscar the Academy gives out and allows the user to select which of some (varying) number of nominations will win an Oscar. The data from each individual session will be publicly available by going to a url like [url].com/answers/[unique id]. The overall data will also be available on a results page. So I've started writing my models file, and this is what I have so far:
from django.db import models
class Nominee(models.Model):
award = models.CharField(max_length=50)
title = models.CharField(max_length=50)
key = modelsCharField(max_length=50)
subtitle = models.CharField(max_length=50)
numVotes = models.IntegerField()
class Session(models.Model):
id = models.IntegerField() # unique id of visitor
bpictureVote = models.ForeignKey(Nominee, related_name = 'nom')
bactorVote = models.ForeignKey(Nominee, related_name = 'nom')
# ... for each award
I was originally thinking of having
class Award(models.Model):
name = models.CharField(max_length=50)
and at the beginning of Nominee,
award = models.ForeignKey(Award, related_name = 'award')
but I couldn't figure out why that would be better than just having award be a part of the Nominee class.
This is really just a start, because I've gotten a bit stuck. Am I on the right track? Should I be doing this totally differently (as I probably should...)? Any thoughts?
Thanks!
You are on the right track.
You need a separate Award class to avoid having to type in award's name every time you create a Nominee. By having a ForeignKey reference you make sure that you can safely rename your award, add additional information about the award (let's say in the future you decide to give each award a separate page with a description and a list of nominees), you also avoid errors which can happen from having a set of different spellings and typos ("Best Engineer Award" and "Best Engineer award"). It also makes sense - your application operates a set of objects: user sessions, nominees and awards.
Few unrelated notes:
You don't need an explicit Session.id field, django ORM creates it for you.
Property names have to be name_with_underscores, not camelCase.
No spaces around "=" in an arguments list: models.ForeignKey(Nominee, related_name='nom').
4 spaces instead of 2 (unless explicitly otherwise specified).
I am not entirely sure, because you do mention multiple nominees per award (assuming this is something like a poll before the actual nomination) a ManyToMany would be your required relation, in order to use also the additional user data.
But in the case you have implemented this as a specific app for nominations and implemented a custom user model then this would be refactored to something else...
Anyway to your current implementation:
class Nominee(models.Model):
title = models.CharField(max_length=50)
key = modelsCharField(max_length=50)
subtitle = models.CharField(max_length=50)
...
class Award(models.Model):
name = models.CharField(max_length=50)
nominees = models.ManyToManyField(Nominee, through='AwardNominees')
...
class AwardNominees(models.Model):
nominee = models.ForeignKey(Nominee)
award = models.ForeignKey(Award)
user = models.ForeignKey(User)
numVotes = models.IntegerField()
....
So it turned out I was thinking about this entirely wrong. I've now completely changed things, and now it's fully functional (!). But in the spirit of full disclosure, I should say that it definitely may not be the best solution. It sure seems like a good one, though, because it's really simple. Now I have only one model:
class Vote(models.Model):
award = models.CharField(...) # Name of the award
title = models.CharField(...) # Title of the nominee
subtitle = models.CharField(...) # Subtitle of the nominee
uid = models.CharField(...) # A 6 character user ID for future access
When I want to show the results of one user's votes, I can use Django's database tools to filter for a certain uid captured in the URL. When I want to tally the votes, I can use a combination of filters and Django's count() to determine how many votes each nominee had for a certain award. Sounds reasonable enough to me!
I'm trying to work out the most django-reffic way to do the following:
Models
class Warehouse(models.Model):
name = models.CharField()
class Product(models.Model):
name = models.CharField()
class ProductStock(models.Model):
product = models.ForeignKey(Product)
warehouse = models.ForeignKey(Warehouse)
qty = models.IntegerField()
What would be the best way to build the forms on the product page knowing that I need to enter the stock for each warehouse?
I know I could just grab the warehouses and iterate over them and build a qty field input then iterate over that on submission, but is there a better way?
Cheers,
Ben
Modelformsets should do the trick. In particular, look into inline modelformsets and inlineformset_factory. They are one of my favourite things in Django, but also a big gnarly if you're a newcomer to the framework.