I am terribly sorry for the crummy title to this question. I can't think of how to phrase it in a simple context.
I am making a simple photo gallery. The admin can create a gallery page and upload images to it. For each gallery I want there to be a single banner image from one of the photos. The Photo model has a CharField which will tell if its a banner or not. Is there a way to make the variable to allow only one 'B' for every photo that belongs to a Gallery?
You should define a unique_together variable for your class. If names of your fields are album and banner, you should add this line to Meta class of your model.
unique_together = (("album", "banner"),)
Django Documents, unique-together
And i think, using charfield for a boolean value isn't a correct choice. You should change your banner field as BooleanField.
Why don't you create a OneToOne field?
class Gallery(models.Model):
...
banner = models.OneToOneField(Photo)
this way, you have an unique relationship between a gallery and a photo.
Related
I have a simple snippet using Django Wagtail. I would like to be able to update the logo from a "CreateView" but when it renders in my view it's expecting a foreign key. I would imagine it would be easy to create a from to do this but it's not.
#register_snippet
class MerchantSnippet(models.Model):
name = models.CharField(max_length=255, blank=False, null=False, unique=True)
logo = models.ForeignKey(
'wagtailimages.Image',
null=True,
blank=True,
on_delete=models.SET_NULL,
)
def __str__(self):
return '{} {}'.format(self.user.first_name, self.user.last_name)
panels =[
FieldPanel('name'),
ImageChooserPanel('logo'),
]
edit_handler = TabbedInterface([
ObjectList(panels, heading='Content'),
])
class ProductCreateView(CreateView):
model = ProductSnippet
fields = ['name','logo']
class ProductUpdateView(UpdateView):
model = ProductSnippet
fields = ['name','logo']
When I use the default example in the template I ended up just getting a drop down.
{% render_field field class+="form-control" %}
How would I be able to see an image preview in the event I am updating the snippet and the ability to upload a different one . In the event I am creating a new item the ability to select an upload an image.
The logo field is a foreign key and points to Wagtail Image. Therefore it is a select. If you change the logo field to a ImageField you probably have the behaviour you desire. However, uploaded logos will not appear in the Wagtail Images. That ain't a bad thing. Whenever you want to display a logo, you'd just use the ​Merchant snippet.
If storing the logo as a Wagtail Image is a must, there are two alternatives:
Alternative 1: Custom form
CreateView and UpdateView are Django generic views and inherit the FormMixin. This means you can specify a custom form_class. Create a custom form with a logo = ImageField(...) and on submit, handle the image data, create a Wagtail Image, and store the Wagtail Image pk on the snippet.
Alternative 2: Multiple forms
Django can handle multiple forms inside a single form tag with a prefix to avoid field name collisions. So you can present both the snippet and the Wagtail image within the same view.
Note: #register_snippet is needed for Wagtail to display CRUD views and enable the snippet chooser in the Wagtail admin interface. But a snippet is a regular Django model. Wagtail Image is a regular Django model too. Forms and generic views are also pure Django concepts. If you dive into this some more, leave Wagtail out of your search queries.
Django==1.11.5
I have two models:
class Sheet(models.Model):
canonical_image = models.ForeignKey('images.Image',
blank=True,
null=True,
on_delete=models.PROTECT,
related_name="%(app_label)s_%(class)s_related",
verbose_name=_("canonical image"))
class Image(models.Model):
sheet = models.ForeignKey(Sheet,
on_delete=models.PROTECT,
verbose_name=_("sheet"))
pass
I registered the models for Django admin.
Now when I change the sheet in admin, I see "Canonical image" and a plus button to add an image.
If I press the plus button, a form for creating a new Image appear.
And there is going to be a drop down list with choices sheets. There is a bunch of sheets there.
This is clumsy. I press a plus sign from a definite sheet. That very sheet should be selected for creation a new image.
Could you tell me how to cope with this problem. Maybe to limit the choice to that particular sheet. Or remove the sheet from image creation form and substitute it in input type="hidden".
Or something else. The easier the better.
This should be a comment, but I do not have enough points for that.
But have you looked into creating a ModelAdmin?
Django doc
In a ModelAdmin class, you can also add inlines for other model, which either links to the model you attach the ModelAdmin to, or models that your current model links to.
I have a video model that stores 'likes' as a manytomany field with User.
e.g
class Video(models.Model):
...
likes = models.ManyToManyField(User)
....
When I create a ModelForm based on Video Likes is displayed as a dropdown with a list of all users. This is obviously ont what I want. I would like a particular user to be able to add/ remove their own name from this list. How do I instead display 'likes' as a checkbox and still have the form validate correctly?
In your model form, create a custom field for likes; when this field is checked, set likes to request.user.
from django import forms
class VideoForm(forms.ModelForm):
likes = forms.BooleanField(label='Mark as favorite?')
class Meta:
model = Video
This will render likes as a checkbox (the default widget for BooleanField).
I would write my own widget for this field (or replace the field with a boolean field): https://docs.djangoproject.com/en/dev/topics/forms/modelforms/#overriding-the-default-field-types-or-widgets
I would like to store groups of pages under different tags. So I create these models:
class Page(models.Model):
title = models.CharField(max_length=50)
class Tag(models.Model):
title = models.CharField(max_length=50)
pages = models.ManyToManyField(Page)
I would then like to create a model form(set?) that will allow me to edit the tag, and every page attached to that tag, as one big form. I believe this is what happens when you use Model Inline Formset, but that uses foreign keys. This is a reusable app, right now I'm just rendering the form in a template, but I would prefer to use django forms so it's easier to reuse.
I can't seem to figure out how this is done, any suggestions would be greatly appreciated.
Take a look at django-tagging application.
I have simple models with generic relations from this example at the Django Project:
class Image(models.Model):
image = models.ImageField(upload_to="images")
class ImageLink(models.Model):
image = models.ForeignKey(Image)
content_type = models.ForeignKey(ContentType)
object_id = models.PositiveIntegerField()
content_object = generic.GenericForeignKey("content_type", "object_id")
class Product(models.Model):
name = models.CharField(max_length=100)
It's very simple to show inline ImageLink objects on the admin form of Product. It is demonstrated in the Django docs.
Can anyone suggest how have related ImageLinks inline on the admin form of an Image model?
IMPORTANT UPDATE: Updated example of model, becourse with previous, as Daniel sayd, it's not need to show objects inline.
It's neccessary use generic.GenericTabularInline for showing ImageLink objects inline on the Product form, as demonstrated in the Django docs.
But if we need to show related ImageLink inline on the Image form, it can be done with simple child of admin.TabularInline class.
It's very simple solution. I think I'm stupid not to guess it right away.
You don't have any related Products to show inline. Generic foreign keys, like normal ones, are one-to-many, with the 'one' side of the relation being the one containing the foreign key field. So in your case you still only have one Product for each Image, so there is no inline set to show.