A game, and lets say there are different (restrictive) settings for recreation and I want to adjust via django admin.
models.py:
class Board(models.Model):
name = CharField()
class Player(models.Model):
bord = Foreignkey('Board')
max_cards = IntegerField()
class Card_Slot(models.Model):
owner = Foreignkey('Player')
card = CharField()
A Board should have a random number of Players associated with it. An inline TabularInline should be used to add or delete Players, with an IntegerField for the max number of Cards (max_cards).
I use signals on save to create dynamically Card_Slots appropriate to the number of max_cards.
--- thats what I have, now what I want ---
'Swapping' the Inline after setting the max_cards, for an Inline that represents the Players and their Cards (thus Playername and card in Card_Slot should be editable).
Several headaches come up for me on that. If possible I don't want to overwrite admin templates. If I should, I would appreciate a hint that goes further then pointing to the docs, meaning pointing in a direction on good practice.
I'm also not sure, if I should use one Model for Player and Card_Slot. (This would make the edit name thing easier, but the dynamic size of Card_Slots worse).. I think.
I have no clue on how I should do that. Pls help.
(One approach appears to be with custom Fieldsets, which I didn't get to work so far. The thought is to replace the content and type of the Integer Field with a ModelMultipleChoiceField related to a queryset of the Card_Slots. But I dont understand how I can do custom Fields on an Inline without a model etc.)
Related
I'm trying to make a select box in the admin that shows a list of objects in the database, outside the current app. Here is my model
from typefaces.models import Typeface
class Word(models.Model):
text = models.CharField(max_length=200)
family_select = models.CharField(max_length=100, choices=Typeface.objects.all)
Unfortunately, Django tells me 'choices' must be an iterable (e.g., a list or tuple). But my attemps to make it iterable with iter() have yielded no success.
This is a completely wrong way to do it. Relationships between models should be specified using OneToOneFields, ForeignKeys (one-to-many field) and ManyToManyFields. You should just change the CharField to this:
family = models.ForeginKey(Typeface, related_name='words')
If you have a specific reason for not using the generally acceptable way, please elaborate on that further to get an answer for that.
I have an idea for data model in django and I was wondering if someone can point out pros and cons for these two setups.
Setup 1: This would be an obvious one. Using CharFields for each field of each object
class Person(models.Model):
name = models.CharField(max_length=255)
surname = models.CharField(max_length=255)
city = models.CharField(max_length=255)
Setup 2: This is the one I am thinking about. Using a ForeignKey to Objects that contain the values that current Object should have.
class Person(models.Model):
name = models.ForeignKey('Name')
surname = models.ForeignKey('Surname')
city = models.ForeignKey('City')
class Chars(models.Model):
value = models.CharField(max_length=255)
def __str__(self):
return self.value
class Meta:
abstract = True
class Name(Chars):pass
class Surname(Chars):pass
class City(Chars):pass
So in setup 1, I would create an Object with:
Person.objects.create(name='Name', surname='Surname', city='City')
and each object would have it's own data. In setup 2, I would have to do this:
_name = Name.objects.get_or_create(value='Name')[0]
_surname = Surname.objects.get_or_create(value='Surname')[0]
_city = City.objects.get_or_create(value='City')[0]
Person.objects.create(name=_name, surname=_surname, city=_city)
Question: Main purpose for this would be to reuse existing values for multiple objects, but is this something worth doing, when you take into consideration that you need multiple hits on the database to create an Object?
Choosing the correct design pattern for your application is a very wide area which is influenced by many factors that are even possibly out of scope in a Stack Overflow question. So in a sense your question could be a bit subjective and too broad.
Nevertheless, I would say that assigning a separate model (class) for first name, another separate for last name etc. is an overkill. You might essentially end up overengineering your app.
The main reasoning behind the above recommendation is that you probably do not want to treat a name as a separate entity and possibly attach additional properties to it. Unless you really would need such a feature, a name is usually a plain string that some users happen to have identical.
It doesn't make any good to keep name and surname as separate object/model/db table. In your setup, if you don't set name and surname as unique, then it doesn't make any sense to put them in separate model. Even worse, it will incur additional DB work and decrease performance. Now, if you set them as unique, then you have to work over the situation when, e.g. some user changes his name and by default it would be changed for all users with that name.
On the other hand, city - there're not that many cities and it's a good idea to keep it as separate object and refer to it via foreign key from user. This will save disk space, allow to easily get all users from same city. Even better, you can prepopulate cities DB and provide autocompletion fro users entering there city. Though for performance you might still want to keep city as a string on the user model.
Also, to mention 'gender' field, since there're not many possible choices for this data, it's worth to use enumeration in your code and store a value in DB, i.e. use choices instead of ForeignKey to a separate DB table.
Before I start: My understanding of Django is at a beginner Level and i could not find adequate help through google.
I'll start with an example:
class Player(models.Model):
...
class Tournament(models.Model):
...
first_place = models.ForeignKey(Player)
second_place = models.ForeignKey(...)
third_place = models.ForeignKey(...)
My problem is: there are multiple people in first place, second place and so on. How can I realize the model in a way which lets me add my own number of Players every time?
I already tried ManyToMany instead of ForeignKey but then I get an Error in the admin menu when i try to save a Tournament Object stating that there has to be an ID present for the Object even when I do not select any Players to be added.
Don't know if I understand the question correctly, but if you want to make ForeignKeys optional and also want to add multiple Players, you could use ManyToManyField and set null and blank, both True:
class Tournament(...):
...
first_place = models.ManyToManyField(Player, blank=True, null=True)
...
This would solve your problem you can now freely add each and any place to each player. The .count() function in your view can get the number of objects for the selected players. No need for a manytomanyfield when you can just assign a place to an object by the user with every user now being able to have unlimited places in each category, if I understand what your trying to do here. Comment if you need more help.
Class FirstPlace(models.Model):
first = models.ForeignKey(Player)
Class SecondPlace(models.Model):
second = models.ForeignKey(Player)
Class ThirdPlace(models.Model):
third = models.ForeignKey(Player)
I have some Django models that record people's listening habits (a bit like Last.fm), like so:
class Artist(models.Model):
name = models.CharField()
class Song(models.Model):
artist = models.ForeignKey(Artist)
title = models.CharField()
class SongPlay(models.Model):
song = models.ForeignKey(Song)
user = models.ForeignKey(User)
time = models.DateTimeField()
class User(models.Model):
# doesn't really matter!
I'd like to have a user page where I can show the top songs that they've listened to in the past month. What's the best way to do this?
The best I've come up with so far is:
SongPlay.past_month
.filter(user=user)
.values('song__title', 'song__id', 'song__artist__name')
.annotate(plays=Count('song'))
.order_by('-plays')[:20]
Above, past_month is a manager that just filters plays from the last month. Assume that we've already got the correct user object to filter by as well.
I guess my two questions are:
How can I get access to the original object as well as the plays annotation?
This just gives me certain values, based on what I pass to values. I'd much rather have access to the original object – the model has methods I'd like to call.
How can I group from SongPlay to Artist?
I'd like to show a chart of artists, as well as a chart of songs.
You can use the same field in both values and annotate.
You have the primary key of the Song object (you could just use song instead of song__id), so use
Song.objects.get(id=...)
For your second question, do a separate query with song__artist as the field in values and annotate:
from django.db.models import Count
SongPlay.past_month
.filter(user=user)
.values('song__artist')
.annotate(plays=Count('song__artist'))
.order_by('-plays')[:20]
agf has already showed you how to group by song_artist. What I would do to get the actual Song object is store it in memcached, or if the method you are calling is rather simplistic make it a static method or a class method. You might could also initialize a Song object with the data from the query and not actually save it to get access to this method. Might help to know the details of the methods you want to call from the Song object.
Howdy. I'm working on migrating an internal system to Django and have run into a few wrinkles.
Intro
Our current system (a billing system) tracks double-entry bookkeeping while allowing users to enter data as invoices, expenses, etc.
Base Objects
So I have two base objects/models:
JournalEntry
JournalEntryItems
defined as follows:
class JournalEntry(models.Model):
gjID = models.AutoField(primary_key=True)
date = models.DateTimeField('entry date');
memo = models.CharField(max_length=100);
class JournalEntryItem(models.Model):
journalEntryID = models.AutoField(primary_key=True)
gjID = models.ForeignKey(JournalEntry, db_column='gjID')
amount = models.DecimalField(max_digits=10,decimal_places=2)
So far, so good. It works quite smoothly on the admin side (inlines work, etc.)
On to the next section.
We then have two more models
InvoiceEntry
InvoiceEntryItem
An InvoiceEntry is a superset of / it inherits from JournalEntry, so I've been using a OneToOneField (which is what we're using in the background on our current site). That works quite smoothly too.
class InvoiceEntry(JournalEntry):
invoiceID = models.AutoField(primary_key=True, db_column='invoiceID', verbose_name='')
journalEntry = models.OneToOneField(JournalEntry, parent_link=True, db_column='gjID')
client = models.ForeignKey(Client, db_column='clientID')
datePaid = models.DateTimeField(null=True, db_column='datePaid', blank=True, verbose_name='date paid')
Where I run into problems is when trying to add an InvoiceEntryItem (which inherits from JournalEntryItem) to an inline related to InvoiceEntry. I'm getting the error:
<class 'billing.models.InvoiceEntryItem'> has more than 1 ForeignKey to <class 'billing.models.InvoiceEntry'>
The way I see it, InvoiceEntryItem has a ForeignKey directly to InvoiceEntry. And it also has an indirect ForeignKey to InvoiceEntry through the JournalEntry 1->M JournalEntryItems relationship.
Here's the code I'm using at the moment.
class InvoiceEntryItem(JournalEntryItem):
invoiceEntryID = models.AutoField(primary_key=True, db_column='invoiceEntryID', verbose_name='')
invoiceEntry = models.ForeignKey(InvoiceEntry, related_name='invoiceEntries', db_column='invoiceID')
journalEntryItem = models.OneToOneField(JournalEntryItem, db_column='journalEntryID')
I've tried removing the journalEntryItem OneToOneField. Doing that then removes my ability to retrieve the dollar amount for this particular InvoiceEntryItem (which is only stored in journalEntryItem).
I've also tried removing the invoiceEntry ForeignKey relationship. Doing that removes the relationship that allows me to see the InvoiceEntry 1->M InvoiceEntryItems in the admin inline. All I see are blank fields (instead of the actual data that is currently stored in the DB).
It seems like option 2 is closer to what I want to do. But my inexperience with Django seems to be limiting me. I might be able to filter the larger pool of journal entries to see just invoice entries. But it would be really handy to think of these solely as invoices (instead of a subset of journal entries).
Any thoughts on how to do what I'm after?
First, inheriting from a model creates an automatic OneToOneField in the inherited model towards the parents so you don't need to add them. Remove them if you really want to use this form of model inheritance.
If you only want to share the member of the model, you can use Meta inheritance which will create the inherited columns in the table of your inherited model. This way would separate your JournalEntry in 2 tables though but it would be easy to retrieve only the invoices.
All fields in the superclass also exist on the subclass, so having an explicit relation is unnecessary.
Model inheritance in Django is terrible. Don't use it. Python doesn't need it anyway.