Refresh on adding many2many in from inline - django

I have inline with many2many field in it.
After adding new record using add button and popup window for manytomany field, newly added record is not shown in other inlines in the page. Also, if I want to add new inline after it, newly added manytomany record does not exist until page is refreshed.
Example:
class Target(models.Model):
name = models.TextField()
class Task(models.Model):
targets = models.ManyToManyField(Target)
section = models.ForeigKey(Section)
class Section(models.Model):
name = models.TextField()
And in admin:
class TaskInline(admin.StackedInline):
model = Task
class SectionAdmin(admin.ModelAdmin):
inlines = (TaskInline,)
If I add new Target from TaskInline form, newly added target cannot be seen in other Task inline forms, nor if I add new Task inline.
Is there a way to refresh the page on Target save, or is there any better solution?

Related

Django rest framework update if item exists

I have the following model:
class Item(models.Model):
itemID = models.IntegerField(unique=True)
url = models.CharField(max_length=300)
name = models.CharField(max_length=300)
price = models.FloatField()
and the following Serializer:
class ItemSerializer(serializers.ModelSerializer):
class Meta:
model= Item
fields = ('id','itemID','url','name','price')
When posting an item that already exists I get the following message:
{"itemID":["item with this itemID already exists."]}
Instead, however, I would like to update all other fields if the item already exists.
It'd be best if you could include your view in your original post. That being said, model views will usually behave like so:
Assuming we have an Item view located at api/item/
To create an item, you POST at api/item/. It is mapped to the create method
To update an item, you PATCH or PUT at api/item/[item_id]/. It is mapped to the update method
To fetch an item, you GET at api/item/[item_id]/. It is mapped to the partial_update method
To delete an item, you DELETE at api/item/[item_id]/. It is mapped to the destroy method
To list all items, you GET at api/item/. It is mapped to the list method
Those methods and urls are automatically available when using the ModelViewSet from Django Rest Framework, though you could override them and make them your own.
When using a ModelSerializer, you have 2 choices when initializing the serializer:
serializer(data=data) will end up creating a new model instance on save
serializer(instance, data=data) will allow you to update an existing instance when saving it

Django Admin: Integrity error on "save as" with GenericForeignKey

What I have:
a) A simple class to store tags:
class Tag(models.Model):
"""
Defines a tag for any model object.
"""
content_type = models.ForeignKey(ContentType)
object_id = models.PositiveIntegerField()
content_object = GenericForeignKey()
type = models.ForeignKey(TagType, related_name='+', verbose_name="Typ", db_column='Typ')
value = models.CharField("Wert", max_length=80, db_column='Wert')
b) A mixin that adds the reverse direction to any class:
class TaggedMixin(models.Model):
""" Mixed into a model class, provides it with the ability to receive tags
(i.e. Tag objects).
"""
_tags = GenericRelation(Tag)
c) And some class, call it Data, that inherits from the Mixin. In the admin, this class uses a GenericTabularInline for Tag to display the Data's tags. It also sets "save_as" to True in order to get the "Save As" button on its admin page.
What happens:
When I click "Save As" for a Data object that has at least one tag, I get:
Integrity Error (1048, "Column 'content_type_id' cannot be null")
To me it seems like Django Admin does not handle GenericForeignKeys properly when doing the "Save As". Is there a way to get it running? A way to work around the problem? Or could I be doing something wrong here?
Perhaps I should add, I am using Django 1.7.7 here.
EDIT: We have upgraded to 1.8.2 and the problem still persists. Any ideas?

Django AttributeError Modifying Field Without Tracking Change History

I am currently running a production Django webapp that holds historic item information using the SimpleHistory feature.
I have a navigation bar that displays all current revisions of all items to click on and view their separate pages. That being said, I wanted to have the ability to select which items to show/hide in the navigation bar by updating a boolean field on the item admin pages.
So, I modified the item models to have a field to do such:
class Item(models.Model)
field1 = models.CharField()
field2 = models.CharField()
...
hide_item = models.BooleanField('Item hidden:', default=True) #don't want history on this field
reason_for_change = models.CharField()
changed_by = models.ForeignKey(User, null=True)
accepted_by = models.ForeignKey(User, null=True)
accepted_date = models.DateTimeField()
history = HistoricalRecords()
def __unicode__(self):
return self.name
def save(self, *args, **kwargs):
super(Item, self).save(*args, **kwargs)
#property
def _history_user(self):
return self.changed_by
#_history_user.setter
self.changed_by = value
After making the migrations, this field showed up in the admin pages to my delight, but unfortunately I am not able to modify this field without receiving the following error:
AttributeError: can't set attribute
C:\Python27\lib\site-packages\simple_history\admin.py in save_model, line 151
151. obj._history_user = request.user
I think it might have to do with the fact that all changes to item field need to be tracked using the SimpleHistory feature, but for this particular field I don't want to track and store the history of its changes, I just want to be able to enable and disable at will in the admin page.
I also noticed, that if I make a new instance of an Item on the webapp and check the value of hide_item on the admin item page, it is False when it should be True by default. On the contrary, if I attempt to add a new Item instance within the admin page, hide_item is set to True by default as expected...
Right now I think my best solution might be to make another model that holds hide/display information for all items and keep it separate from the item models.
Wondering if anyone might now how to accomplish this.
Thanks
Might not be the most elegant way to do it, but I ended up making a separate model that stores show/hide information and syncs with the item to be displayed.
I did this using a BooleanField for the show/hide and a readonly OneToOne(Item) field to sync with the item I want to display.
Worked well.

Adding to List Style Entries in Django Admin

I would like to create a model where the user can add objects of a model to a list in Django.
For example:
class Receipt(models.Model):
items = #many to many maybe? but their is only one receipt for each item object
#other fields
class Item(models.Model):
name = model.CharField()
#otherfields
Class ItemPurchase(models.Model):
receipt = model.ForeignKey(Receipt)
item = model.ForeignKey(Item)
quantity = model.IntegerField()
#other fields specific to this Receipt
Then in the admin, I want to allow the user to add Item objects to their current Receipt objects in the admin panel, and create an ItemPurchase record, but how would I best do this? The Receipt cannot be associated until the Receipt is made...
Turns out Django's inline feature combined with custom queryset returns is exactly what I needed to do everything I wanted, thanks #Hedde for the tip!
Read about inlines:
https://docs.djangoproject.com/en/dev/ref/contrib/admin/#inlinemodeladmin-objects
This helped in multiple ways, I just needed a push in the right direction:
formfield_for_foreignkey and Inline Admin

Check if model instance is FKed inside a queryset?

I have a model:
class ProjectBookmark(models.Model):
user = models.ForeignKey(User)
project = models.ForeignKey('Project')
say a user is viewing a project, is there a way to somehow check if current project is in users bookmarks other than a nasty way I do this now via request context as bellow? Basically, users bookmarks are a list of projects and checked as
{% if current_project in current_user.bookmarks %}...
right from inside the template?
the_user = request.user
bookmarked_projects = list()
for b in ProjectBookmark.objects.filter(user = request.user):
bookmarked_projects.append(b.project_id)
the_user.bookmarks = Project.objects.filter(id__in=bookmarked_projects)
return {'current_user':request.user}
For use directly in a template, the best way to go would be creating a custom template tag. Check out the template tag docs.
As for the filtering code itself, it would be very helpful to provide related_name arguments to the ForeignKey fields in the model definition. For example:
class ProjectBookmark(models.Model):
user = models.ForeignKey(User, related_name="project_bookmarks")
project = models.ForeignKey('Project', related_name="bookmarks")
This way you could access a QuerySet object containing all the users bookmarks using request.user.project_bookmarks.all()