Django ModelForm or Form - django

i am totally new to both Python and Django,so please excuse me if this question is a bit simpleton.
I am writing a small app to track the scores of a Billiards match. I don't need to explain all the details, but the basic objects involved are:
Team has Players
Match is between two Teams (home and away)
Match has a collection of Games.
Each Game is between two Players (one from each team), excluding players who have already played in the Match.
I have made the following models:
class Team(models.Model):
team_id = models.IntegerField(unique=True, max_length=5, blank=False,validators=[validate_five_digits])
name = models.CharField(max_length=50, blank=False, null=False)
class Player(models.Model):
id = models.IntegerField(unique=True, max_length=5, blank=False,validators=[validate_five_digits])
team = models.ForeignKey(Team, blank=True, null=True)
first_name = models.CharField(max_length=50, blank=False, null=False)
last_name = models.CharField(max_length=50, blank=False, null=False)
alias_name = models.CharField(max_length=50, blank=True, null=True)
current_handicap = models.IntegerField()
class Match(models.Model):
date = models.DateField(blank=False, null=False)
location = models.CharField(max_length=255, blank=True, null=True)
table_size = models.CharField(max_length=50, blank=True, null=True)
home_team = models.ForeignKey(Team, related_name='home_team', blank=True, null=True)
away_team = models.ForeignKey(Team, related_name='away_team', blank=True, null=True)
class Game(models.Model):
match = models.ForeignKey(Match, blank=False, null=False)
match_sequence = models.IntegerField(blank=True, null=True)
player1 = models.ForeignKey(Player,related_name='player1', blank=False, null=False)
player2 = models.ForeignKey(Player,related_name='player2', blank=False, null=False)
player1_handicap = models.IntegerField(null=True, blank=True)
player2_handicap = models.IntegerField(null=True, blank=True)
I have successfully made Views and ModelForms to add/edit Teams, Players and Matches.
The list of Matches is displayed in a table, with 1 match per row....and now I want to put a button to add a new Game.
My plan is to do so by having the button go to a url that looks like this:
game/new/?match_id=1 (or something like that)
Now for the part where i am confused.....When you go to add a new game, i want to display 3 choice fields, and only 3 choice fields.
First Choice field should display Players from Home Team that have not yet played a game in this match
Second Choice field should display Players from Away Team that have not yet played a game in the match
Third Choice Field would only have two choices (Home and Away)....and would indicate which player gets to shoot first.
Then, when user clicks Submit it needs to create a Game() object with the match_id from the query string, the next sequence number for the match, and Player1 = either home or away player, based on 3rd choice field.
I am totally confused about how this should be done....should i be using a forms.Form or a ModelForm?
Any suggestions or skeleton code to clue me in?
Thanks in advance for help with such a newbie question!
Paul

What type of form class to use when building a Django app is a simple problem. If you're editing a model, use a ModelForm, otherwise use a Form.
If you need to limit choices or alter choices based on other data, you can still do that with a ModelForm by overriding the form's __init__()
Using a ModelForm will reduce the amount of code necessary to add the Game instance, because a ModelForm already knows how to create or update an instance of Game. You'd have to handle that yourself if you were just using a Form class.

Related

django multilevel nested formsets

django provide inline formset which allow to 3rd level of nesting, but I need much more complex nesting. It should be fully dynamic, so I can go one to one on each level, but it could be one to many on each level. So far I have this only, but could be expanded for additional sublevels.
class Srts(models.Model):
data = models.CharField(max_length=10, blank=True, null=True)
class Volume(models.Model):
srts = models.ForeignKey('Srts', on_delete=models.CASCADE)
name = models.CharField(max_length=120, blank=True, null=True)
class Qtree(models.Model):
volume = models.ForeignKey('Volume', on_delete=models.CASCADE)
name = models.CharField(max_length=120)
class Server(models.Model):
qtree = models.ForeignKey('Qtree', on_delete=models.CASCADE)
hostname = models.CharField(max_length=120, blank=True, null=True)
class CifsPermission(models.Model):
qtree = models.ForeignKey('Qtree', on_delete=models.CASCADE)
group = models.CharField(max_length=30, blank=True, null=True, default='None')
permission = models.CharField(max_length=30, blank=True, null=True, default='None')
I have been googling a lot last days, but there is not much.
Some examples
django-nested-inline-formsets-example -that basic only 3rd level
Django-better forms -could handle multiple forms on one submit, but not formsets
django-nested-inline -only for admin page
Shoudl be the way to work with not model related form , then do some separation and appropriate logic and then save it to models?
can't add image, some sever error ocured, so giving the link directly
https://imgur.com/a/NQBR6tJ
I would like to to something simular over normal view, not admin view.

Django full text search on multiple related field returning duplicate data

Consider I have below models.
class BoardStatus(models.Model):
status = models.CharField(max_length=10, primary_key=True)
class Board(models.Model):
board_id = models.SlugField(db_index=True, max_length=10, unique=True)
creator = models.ForeignKey(User, on_delete=models.CASCADE, related_name="board_creator", db_index=True)
status = models.ForeignKey(Status, related_name="board_status",
on_delete=models.CASCADE)
class BoardData(models.Model):
board = models.ForeignKey(Board, related_name="board_data", on_delete=models.CASCADE)
ip = models.GenericIPAddressField(db_index=True)
host = noa_mail_hostname = models.CharField(db_index=True, max_length=100)
address = models.CharField(db_index=True, max_length=200, blank=True)
Class BoardMailData(models.Model):
board = models.OneToOneField(Board, related_name="board_mail_data", on_delete=models.CASCADE)
subject = models.CharField(max_length=100, null=True, blank=True)
For testing, I created 5 board objects with the same user and assigned the related tables to each board.
Let's consider in the created test data, one of the boards has a subject (related field) "Test Subject".
Now I want to do a full-text search on multiple related fields from the parent model i.e Board and I have the below query for that
filtered_qs_data = Board.objects.filter(status="some status")
filtered_qs_data.annotate(
search=SearchVector(
"creator__user_name", "board_mail_data__subject",
"board_id", "creator__user_id", "board_data_host",
"board_data__address" "board_data__ip"
)).filter(search=SearchQuery("test subject", search_type='phrase')).distinct()
So Even though I have given distinct, the search value should return a single record from the DB, but it is returning single duplicate records. What I mean here is that it is returning the same "test subject" multiple times.
I'm really not sure what I'm doing wrong here. Please someone help me.

Django, o2o/one-to-one modeling with multiple models

I have a model Job.
class Job(models.Model):
job_number = models.AutoField(primary_key=True)
date_opened = models.DateField()
staff_opened = models.ForeignKey(User, related_name="jobs_opened")
date_closed = models.DateField(blank=True, null=True)
staff_closed = models.ForeignKey(User, related_name="jobs_closed", db_index=True, blank=True, null=True)
date_promised = models.DateField(blank=True, null=True)
date_estimate = models.DateField(blank=True, null=True)
customer = models.CharField("Customer", max_length=50, db_index=True)
slug = models.SlugField(max_length=60, unique=True)
And I also have a number of different type of jobs that hold more information, depending on what it is:
class WorkshopJob(Job):
job = models.OneToOneField(Job, parent_link=True)
invoice_number = models.CharField("Invoice Number", max_length=30, blank=True)
part = models.ForeignKey(PartNumber)
serial_number = models.CharField(max_length=20, blank=True)
and
class EngineeringJob(Job):
job = models.OneToOneField(Job, parent_link=True)
work_order = models.CharField(max_length=30)
reported_fault = models.TextField()
findings = models.TextField(blank=True)
work_performed = models.TextField(blank=True)
Any particular Job can only have one Engineering Job, one Workshop Job - but it can have one of each, too.
I never instantiate a Job on it's own - there is no AddJob view or page - only the subclasses.
The part I'm struggling with is the link - if I am viewing the detail of one subclass, how can I "add" another type of Job to the same Job?
IE if the I had an engineering job with job_id=1, how do I "pass" the job_id=1 to the new Workshop Job in the view?
I've tried adding get_initial(self) to the views, but it isn't working for me.
I think I'm going to rejig my set up.
Previously I had urls like this:
url(r'^workshop/add/$', views.WorkshopJobAdd.as_view(), name='wsjob_add'),
url(r'^workshop/(?P<slug>[-\w]+)/$', views.WorkshopJobDetail.as_view(), name='wsjob_detail'),
url(r'^workshop/(?P<slug>[-\w]+)/edit/$', views.WorkshopJobEdit.as_view(), name='wsjob_edit'),
url(r'^workshop/(?P<slug>[-\w]+)/invoice/$', views.WSJInvoice.as_view(), name='wsj_invoice'),
url(r'^engineering/add/$', views.EngineeringJobAdd.as_view(), name='wsjob_add'),
url(r'^engineering/(?P<slug>[-\w]+)/$', views.EngineeringJobDetail.as_view(), name='wsjob_detail'),
url(r'^engineering/(?P<slug>[-\w]+)/edit/$', views.EngineeringJobEdit.as_view(), name='wsjob_edit'),
url(r'^engineering/(?P<slug>[-\w]+)/invoice/$', views.EngineeringInvoice.as_view(), name='wsj_invoice'),
And was trying to pass the job_id between views.
But I think the easiest/sensible solution to my problem is to change the urls to something more like:
url(r'^job/(?P<slug>[-\w]+)/workshop/add/$', views.WorkshopJobAdd.as_view(), name='wsjob_add'),
url(r'^job/(?P<slug>[-\w]+)/workshop/$', views.WorkshopJobDetail.as_view(), name='wsjob_detail'),
url(r'^job/(?P<slug>[-\w]+)/workshop/edit/$', views.WorkshopJobEdit.as_view(), name='wsjob_edit'),
url(r'^job/(?P<slug>[-\w]+)/workshop/invoice/$', views.WSJInvoice.as_view(), name='wsj_invoice'),
And then adding a new subclassed model to an existing Job would just be a matter of using the slug. I was making things far to hard for myself.
I think this is another case of "CBVs aren't always the best solution".
Which is not the end of the world - I think I do wish for an easy way to tell when it's the case though :\

Django model: manytomany with more than one object

I have an Event model. Events can have many 'presenters'. But each presenter can either 1 of 2 different types of profiles. Profile1 and Profile2. How do I allow both profiles to go into presenters?
This will be 100% backend produced. As to say, admin will be selecting "presenters".
(Don't know if that matters or not).
class Profile1(models.Model):
user = models.ForeignKey(User, null=True, unique=True)
first_name = models.CharField(max_length=20, null=True, blank=True)
last_name = models.CharField(max_length=20, null=True, blank=True)
created = models.DateTimeField(auto_now_add=True)
modified = models.DateTimeField(auto_now=True)
about = models.TextField(null=True, blank=True)
tags = models.ManyToManyField(Tag, null=True, blank=True)
country = CountryField()
avatar = models.ImageField(upload_to='avatars/users/', null=True, blank=True)
score = models.FloatField(default=0.0, null=False, blank=True)
organization = models.CharField(max_length=2, choices=organizations)
class Profile2(models.Model):
user = models.ForeignKey(User, null=True, unique=True)
first_name = models.CharField(max_length=20, null=True, blank=True)
last_name = models.CharField(max_length=20, null=True, blank=True)
created = models.DateTimeField(auto_now_add=True)
modified = models.DateTimeField(auto_now=True)
about = models.TextField(null=True, blank=True)
tags = models.ManyToManyField(Tag, null=True, blank=True)
country = CountryField()
avatar = models.ImageField(upload_to='avatars/users/', null=True, blank=True)
score = models.FloatField(default=0.0, null=False, blank=True)
...
class Event(models.Model):
title = models.CharField(max_length=200)
sub_heading = models.CharField(max_length=200)
presenters = ManyToManyField(Profile1, Profile2, blank=True, null=True) ?
...
# I've also tried:
profile1_presenters = models.ManyToManyField(Profile1, null=True, blank=True)
profile2_presenters = models.ManyToManyField(Profile2, null=True, blank=True)
# is there a better way to accomplish this?...
I think you have a desing problem here. In my opinion, you must think what is a Presenter and what's the different between a Presenter with "profile 1" and with "profile 2". What are you going to do with this models? Are you sure there are just two profiles? Is there any chance that, in some time from now, a different profile ("profile 3") appears? And profile 4? and profile N?
I recommend you to think again about your models and their relations. Do NOT make this decision thinking of how difficul/easy will be to handle these models from django admin. That's another problem and i'll bet that if you think your models a little bit, this won't be an issue later.
Nevertheless, i can give you some advice of how to acomplish what you want (or i hope so). Once you have think abount how to model these relations, start thinking on how are you going to write your models in django. Here are some questions you will have to answer to yourself:
Do you need one different table (if you are going to use SQL) per profile?
If you cannot answer that, try to answer these:
1) What's the difference between two different profiles?
2) Are there more than one profile?
3) Each presenter have just one profile? What are the chances that this property changes in near future?
I don't know a lot about what you need but i think the best option is to have a model "Profile" apart of your "Presenter" model. May be something like:
class Profile(models.Model):
first_profile_field = ...
second_profile_field = ...
# Each presenter have one profile. One profile can "represent"
# to none or more presenters
class Presenter(models.Model):
first_presenter_field = ....
second_presenter_field = ....
profile = models.ForeignKey(Profile)
class Event(models.Model):
presenters = models.ManyToManyField(Presenter)
....
This is just an idea of how i imagine you could design your model. Here are some links that may help you once you have design your models correctly and have answered the questions i made to you:
https://docs.djangoproject.com/en/dev/topics/db/models/#model-inheritance
https://docs.djangoproject.com/en/dev/misc/design-philosophies/#models
http://www.martinfowler.com/eaaCatalog/activeRecord.html
And to work with the admin once you decide how your design will be:
https://docs.djangoproject.com/en/dev/ref/contrib/admin/
EDIT:
If i'm not wrong, the only difference between profile 1 and 2 fields is the "organization" field. Am i right? So i recommend you to merge both models since they are almost the same. If they have different methods, or you want to add different managers or whatever, you can use the proxy option of django models. For example, you can do this:
class Profile(models.Model):
#All the fields you listed above, including the "organization" field
class GoldenProfile(models.Model):
#you can define its own managers
objects = GoldenProfileManager()
....
class Meta:
proxy = True
class SilverProfile(models.Model):
....
class Meta:
proxy = True
This way, you can define different methods or the same method with a different behaviour in each model. You can give them their own managers, etcetera.
And the event class should stay like this:
class Event(models.Model):
title = models.CharField(max_length=200)
sub_heading = models.CharField(max_length=200)
presenters = ManyToManyField(Profile, blank=True, null=True)
Hope it helps!

Haystack searching multiple fields

I am currently building a page in django, where there are 4 form fields, 2 text, 2 select fields, and when submitted it takes those fields and searches several models for matchinng items.
the model looks like this:
class Person(models.Model):
user = models.ForeignKey(User, blank=True, null=True, verbose_name="the user associated with this profile")
first_name = models.CharField(max_length=255)
last_name = models.CharField(max_length=255)
about = models.TextField(max_length=255, blank=True, null=True)
birthdate = models.DateField(blank=True, null=True, verbose_name="Birthdate (yyyy-mm-dd)")
GENDER_CHOICES = (
(u'M', u'Male'),
(u'F', u'Female'),
)
gender = models.CharField(max_length=1, choices = GENDER_CHOICES, default = 'M')
picture = models.ImageField(upload_to='profile', blank=True, null=True)
nationality = CountryField(blank=True, null=True)
location = models.CharField(max_length=255, blank=True, null=True)
command_cert = models.BooleanField(verbose_name="COMMAND certification")
experience = models.ManyToManyField('userProfile.MartialArt', blank=True, null=True)
and I am trying to search the first_name field, the last_name field, the nationality field, and the experience field, but say if the first_name field is blank, I need to pass an empty value so it returns all rows, then filter from there with last name the same way, for some reason it is not working at all for me. this is my sqs:
results = SearchQuerySet().models(Person).filter(first_name=sname, last_name=slastname, nationality=scountry, experience__pk=sexperience)
any ideas?
Without seeing specific errors or a stack trace, it's hard to determine what "is not working at all".
Edit: Looking at your provided view code, I would remove the filter and return all of the objects for your Fighter, Referee, Insider, and Judge models. This is to ensure that the issue here lies in the filter, and not something else.
Then, once I'd verified that objects are being placed into results, I'd put in the filters one at a time to determine what the problematic filter is. Give this a try and reply back with your results.