Django Forms With foreign key - django

I have 2 models in django, and im also using ModelForm, my question is the second model have a froreignkey of the 1, and i want to have one page when generating the form. It's possible, how to link the two forms in one page.
Class Event(models.Model):
id = models.AutoField(primary_key=True)
name = models.CharField()
class Date(models.Model):
id = models.AutoField(primary_key=True)
start = models.DateTimeField()
end = models.DateTimeField()
event = models.ForeignKey("Event")
I also have
class EventForm(ModelForm)
Class Date(ModelForm)
What i want is to create the event in one page in my templates.
Thanks.

If you want to have this on the Django Admin, then you need to use inline models.
If you plan to create your own form (using ModelForms), then you need to use inline formets.

Related

Can I use unique_together on ManyToMany field?

I have a model OrderPage which is manytomany to Site. In Django admin, I want to restrict the selection of sites(Sites which belong to existing OrderPage can not be selected again). Can I do it with unique_together ? I get an error with following model ManyToManyFields are not supported in unique_together
class OrderPage(models.Model):
description = models.CharField(max_length=255, blank=False)
sites = models.ManyToManyField(Site)
class Meta:
unique_together = (('id', 'sites'),)
class Order(models.Model):
order_page = models.ForeignKey(OrderPage)
class OrderPageAdmin(admin.ModelAdmin):
filter_horizontal = ('sites',)
admin.site.register(OrderPage, OrderPageAdmin)
If an Site can have only one OrderPage, you don't need to worry about unique_together.
Ideally you should subclass Site and use a ForeignKey from that to OrderPage. That would natively give you what you're looking for: each site would be able to have one OrderPage, and each OrderPage multiple Sites. This would be the cleanest but you would have to use your subclass throughout the program in place of the original Site which might be more work than you want right now.
class BetterSite(Site):
order_page = models.ForeignKey('OrderPage')
The dirtier way is to keep your M2M and just set the site as unique, since there should only ever be one entry on each site in the M2M table. You would use a 'through' table so you could set the custom uniqueness value:
class OrderPage(models.Model):
description = models.CharField(max_length=255, blank=False)
sites = models.ManyToManyField(Site, through='OrderPageToSite')
class OrderPageToSite(models.Model):
order_page = models.ForeignKey(OrderPage)
site = models.ForeignKey(Site, unique=True)
(Note that I've left these simple but in your FK fields you should also consider setting on_delete and related_name)

Create forms from model, save to another

I'm building a survey-type app, where the questions are entered/stored in a model (by an admin). I want to use this model to auto-create a user facging form (the response will be stored in another model.
class Question(models.Model):
question_text = models.CharField(max_length=150)
questionnaire = models.ForeignKey(Questionnaire) # 'lump' questions together
class Response(models.Model):
question = models.ForeignKey(Question)
response_text = models.CharField(max_length=150)
user = models.IntegerField() # used to record user ID
I'm not sure what's the correct approach - using a ModelForm (populating through init) or a 'regular' form - where I'm not sure how I output my results - using print or adding to a form property.
Thanks.
In your init you can
self.fields['your_field']=forms.ModelChoiceField(queryset=YourQuerySet.objects.get(pk=X)) // alternatively a filter with first()
to enforce the initial foreign key object

Django forms with odd model relationship

I am working with an existing database that I can not modify and having some trouble trying to deal with presenting forms for modifying the database in Django. The structure in question is as follows and all models are unmanaged.
class Persons(models.Model):
personid = models.BigIntegerField(primary_key=True, db_column='PersonID')
....
class Phones(models.Model):
phoneid = models.BigIntegerField(primary_key=True, db_column='PhoneID')
number = models.CharField(max_length=60, db_column='Number', blank=True)
type = models.CharField(max_length=15, db_column='Type', blank=True)
...
class Personsphones(models.Model):
personphoneid = models.BigIntegerField(primary_key=True, db_column='PersonPhoneID')
personid = models.ForeignKey(Persons, db_column='PersonID')
phoneid = models.ForeignKey(Phones, db_column='PhoneID')
...
I want to create a form to display all of the 'Phones' associated with a particular 'Persons' and in addition be able to modify/add/remove 'Phones' belonging to a 'Persons'. Right now the only thing I can think of is to display the 'Phones' in a modelformset and then if one is added or removed manually set the 'Personsphones' relation. Any ideas on how to best deal with this model setup?
For making changes to your models you may want to use django-south http://south.aeracode.org/docs/
As far as displaying your 'Phone' under your forms.py you may want to set up class meta like so. With this any changes made to models will reflect on change
class Meta:
model = Persons
exclude = ('user')
In models you may want to use Foreignkey fore relationships between phones and Persons. Better seen in action here https://docs.djangoproject.com/en/dev/ref/models/fields/#foreignkey

Django form linking 2 models by many to many field

I have two models:
class Actor(models.Model):
name = models.CharField(max_length=30, unique = True)
event = models.ManyToManyField(Event, blank=True, null=True)
class Event(models.Model):
name = models.CharField(max_length=30, unique = True)
long_description = models.TextField(blank=True, null=True)
I want to create a form that allows me to identify the link between the two models when I add a new entry. This works:
class ActorForm(forms.ModelForm):
class Meta:
model = Actor
The form includes both name and event, allowing me to create a new Actor and simultaneous link it to an existing Event.
On the flipside,
class EventForm(forms.ModelForm):
class Meta:
model = Event
This form does not include an actor association. So I am only able to create a new Event. I can't simultaneously link it to an existing Actor.
I tried to create an inline formset:
EventFormSet = forms.models.inlineformset_factory(Event,
Actor,
can_delete = False,
extra = 2,
form = ActorForm)
but I get an error
<'class ctg.dtb.models.Actor'> has no ForeignKey to <'class ctg.dtb.models.Event'>
This isn't too surprising. The inlineformset worked for another set of models I had, but this is a different example. I think I'm going about it entirely wrong.
Overall question: How can I create a form that allows me to create a new Event and link it to an existing Actor?
Personally, I would put the ManyToMany on Event to begin with, but to each their own...
As for how to do it, you'd want to write a custom ModelForm (not an inline formset), let's call it EventForm. It would handle all of your event's fields and would also have a ModelChoiceField or ModelMultipleChoiceField to allow selection of the Actor(s) involved. Then in your view you would split out the processing of the Event fields and the ForeignKey/M2M field.
Make sense? alt text http://sonicloft.net/im/52

How to create a unique_for_field slug in Django?

Django has a unique_for_date property you can set when adding a SlugField to your model. This causes the slug to be unique only for the Date of the field you specify:
class Example(models.Model):
title = models.CharField()
slug = models.SlugField(unique_for_date='publish')
publish = models.DateTimeField()
What would be the best way to achieve the same kind of functionality for a non-DateTime field like a ForeignKey? Ideally, I want to do something like this:
class Example(models.Model):
title = models.CharField()
slug = models.SlugField(unique_for='category')
category = models.ForeignKey(Category)
This way I could create the following urls:
/example/category-one/slug
/example/category-two/slug
/example/category-two/slug <--Rejected as duplicate
My ideas so far:
Add a unique index for the slug and categoryid to the table. This requires code outside of Django. And would the built-in admin handle this correctly when the insert/update fails?
Override the save for the model and add my own validation, throwing an error if a duplicate exists. I know this will work but it doesn't seem very DRY.
Create a new slug field inheriting from the base and add the unique_for functionality there. This seems like the best way but I looked through the core's unique_for_date code and it didn't seem very intuitive to extend it.
Any ideas, suggestions or opinions on the best way to do this?
What about unique_together?
class Example(models.Model):
title = models.CharField()
slug = models.SlugField(db_index=False)
category = models.ForeignKey(Category)
class Meta:
unique_together = (('slug','category'),)
# or also working since Django 1.0:
# unique_together = ('slug','category',)
This creates an index, but it is not outside of Django ;) Or did I miss the point?