How do I test a Django model with ImageSpecField? - python

I got a following model:
class Room(models.Model):
order = models.SmallIntegerField()
name = models.CharField(max_length=20)
background = models.ImageField(upload_to='room_background', blank=False, null=False)
background_preview = ImageSpecField(source='background', processors=[ResizeToFit(300, 400)])
def serialize(self):
room_dict = model_to_dict(self)
room_dict['background_preview_url'] = self.background_preview.url
return room_dict
I'm not using room object directly on my views, instead I convert them to dict, extending with the 'background_preview_url' key.
Now I want to write some Django tests, using serialized room objects. The issue is that if I just do:
test_room = Room(order=1)
test_room.save
test_room.serialize()
The ImageKit throws a MissingSource error, as there's no background image in my test room to generate preview from.
How do I better overcome that in my tests? Should I carry a fixture with the backgroud images?
Or should I write second serialize_for_test() method?
Or maybe I can instanciate the Room() with some test value for the background_preview field? - I tried this but the direct Room(background_preview='fake_url') didn't work.
Thanks.

The solution, which worked for me:
from django.core.files.uploadedfile import SimpleUploadedFile
test_room.image = SimpleUploadedFile(name='foo.gif', content=b'GIF87a\x01\x00\x01\x00\x80\x01\x00\x00\x00\x00ccc\x00\x00\x00\x00\x01\x00\x01\x00\x00\x02\x02D\x01\x00')
test_room.save

Related

what's the purpose of customizing django models

I read the following code for customizing Document model.
class DocumentQuerySet(models.QuerySet):
def pdfs(self):
return self.filter(file_type='pdf')
def smaller_than(self, size):
return self.filter(size__lt=size)
class DocumentManager(models.Manager):
def get_queryset(self):
return DocumentQuerySet(self.model, using=self._db) # Important!
def pdfs(self):
return self.get_queryset().pdfs()
def smaller_than(self, size):
return self.get_queryset().smaller_than(size)
class Document(models.Model):
name = models.CharField(max_length=30)
size = models.PositiveIntegerField(default=0)
file_type = models.CharField(max_length=10, blank=True)
objects = DocumentManager() #overriding the default model manager
Now suppose i want to retreive files of type pdf and size less than 1000.
Then i need to do the following:
Document.objects.pdfs().smaller_than(1000)
But what's the use of doing this even when i could have simply obtained the desired result by filtering the default model manager 'objects' using the following command:
Document.objects.filter(file_type='pdf', size__lt=1000)
What is the difference in the execution of above two commands?
Manager and Queryset methods are defined and used in order to use repeatable code.
If your use case only happens once, perhaps you are better off being explicit in your query, however if you repeat the exact same code elsewhere, perhaps you are better off making it a manager/queryset method.

Django 1.11 Image Gallery with Django Filer

Problem
I need to display a gallery of images on a product page. This worked when we were at Django 1.6, but have since upgraded to Django 1.11 (Big Process). I am now stuck at how to get this to work within the new environment. Right now clicking Add Image brings up a pop up where I can select the image, and the regions associated with it (US, Canada, Spain, Etc..), but after clicking "Save" The popup title changes to Popup closing... and never closes - also the image is not added to the gallery. The image I upload itself IS added to the rest of the Images within filer, however it is not added to the ProductGallery Model.
What I've Got
Django: 1.11.7
Django-Filer: 1.2.7
Django-Suit: 0.2.25
Vanilla-Views: 1.0.4
I have Product models, these products have a many to many relationship to a ProductGallery model like so:
class Product(models.Model):
gallery = models.ManyToManyField('products.ProductGallery')
The ProductGallery is supposed to house Images and Videos allowing for upload of either, and providing one list to iterate through on the front end for display purposes.
The ProductGallery is defined as:
class ProductGallery(models.Model):
limit = models.Q(app_label='media', model='image') | models.Q(app_label='media', model='video')
order = models.PositiveIntegerField(default=0)
content_type = models.ForeignKey(ContentType, limit_choices_to=limit)
object_id = models.PositiveIntegerField(db_index=True)
content_object = generic.GenericForeignKey('content_type', 'object_id')
class Meta:
ordering = ('order',)
def __str__(self):
return six.text_type(self.content_object)
where media.image is defined as: (I'll ignore video for the time being)
class Image(CountryInfoModel, models.Model):
image = FilerImageField(null=True, blank=True)
def __str__(self):
return str(self.image.name or self.image.original_filename)
I've got a view for Adding new Media like so:
class AddMedia(LoginRequiredMixin, StaffuserRequiredMixin, JsonRequestResponseMixin, GenericView):
require_json = True
def post(self, request, *args, **kwargs):
object_id = self.request_json["objectId"]
object_var = self.request_json["objectVarName"]
content_type_id = self.request_json["contentType"]
order = self.request_json["order"]
media_id = self.request_json["mediaId"]
media_type = self.request_json["mediaType"]
content_type = _get_content_type_or_404(content_type_id)
content_object = _get_object_or_404(content_type, object_id)
model_var = getattr(content_object, object_var)
try:
if media_type.lower() == "image":
obj = Image.objects.get(pk=media_id)
elif media_type.lower() == "video":
obj = Video.objects.get(pk=media_id)
else:
raise Http404("Invalid mediaType parameter: {0}".format(media_type))
media_item = model_var.create(content_object=obj)
media_item.order = order
media_item.save()
except model_var.model.DoesNotExist:
pass
return self.render_json_response({'message': "Order successfully updated"})
And I think thats all the pieces there are to this. I am lost on why when I click "save" the Image is not saved to the ProductGallery model at all. I'd be happy to provide more context if needed, and any help is very much appreciated.
Just in case anyone else comes across this and wants to know how it was fixed.
It turns out that some of the django-admin template functionality had been overwritten and was causing some issues.
Specifically this project had overwritten parts of the save button functionality. The function dismissAddRelatedObjectPopup used to be named dismissAddAnotherPopup
These functions were overwritten to provide the custom functionality outlined above with the ProductGallery. Django went to call the function, but this was throwing an error on the popup related to something called SelectBoxwhich then broke the ajax call that was needed to save the model correctly.
Hopefully this can help someone in the future!

how to get datetime instance?

Well it is look like simple question. but i am in the learning stage can`t figure out.
This is my model class
class Store(models.Model):
file = models.FileField(upload_to=content_file_name)
file_name = models.CharField(max_length=100)
created_date = models.DateTimeField(auto_now_add=True)
userfild = models.ForeignKey(user,null=True, blank=True)
Ok for some clarification i just included my content_file_name function here
def content_file_name(instance, filename):
return os.path.join(
"user_%d" % instance.created_date, filename)
but the output of the folder structure looks like this
`None`
----filename
i can get the file_name instance like this --> intance.file_name
but when i enter instance.created_date it is return 'None' value.
What i am missing.? And my another doubt is i set it DateTimeField as auto_now_add=True So it`s saved into the db when form is submitted. But why None return?
auto_now_add is not populated until the object is saved. If you want a default that is applied as soon as the object is instantiated, use the default parameter with a callable:
created_date = models.DateTimeField(default=datetime.datetime.now)
Not quite sure that this is what you're asking, but here goes anyway:
You create an instance of any class by instantiating it:
Store()
In Python, this calls the class's init() function. Since you don't have one, it will use the 'constructor' from the class you're inheriting from, models.Model.
So, for example, you could do something like this:
my_store = Store()
my_store.file_name = 'some new name!'

How do I cascade delete in this scenario using MongoEngine?

I have this simple model:
from mongoengine import *
from datetime import datetime
class Person(Document):
firstname = StringField(required=True)
#property
def comments(self):
return Comment.objects(author=self).all()
class Comment(Document):
text = StringField(required=True)
timestamp = DateTimeField(required=True, default=datetime.now())
author = ReferenceField('Person', required=True, reverse_delete_rule=CASCADE)
class Program(Document):
title = StringField(required=True)
comments = ListField(ReferenceField('Comment'))
class Episode(Document):
title = StringField(required=True)
comments = ListField(ReferenceField('Comment'))
As you can see, both Programs and Episodes can have comments. Initially, I tried to embed the comments but I seemed to run into a brick wall. So I'm trying Comments as a Document class instead. My question is, how do I model it so that:
When a Person is deleted, so are all their comments
When a Comment is deleted (either directly or indirectly), it is removed from its parent
When a Program or Episode is deleted, so are the Comment objects
I'm use to doing all this manually in MongoDB (and SQLa, for that matter), but I'm new to MongoEngine and I'm struggling a bit. Any help would be awesome!
Not all of these are possible without writing application code to handle the logic. I would write signals to handle some of the edge cases.
The main issue you have is global updates / removes aren't handled - so you'd have to ensure that the api you write in the api is used, to ensure a clean database state.

Database modeling in django

I have a situation I don´t know how to model correctly. I want every child of a class to be associated with a media object (photo, video or music). I want to know which is the preffered approach to this problem. What I have right now is:
class Something(models.Model):
media = models.ForeignKey(Media)
class Media(models.Model):
title = models.CharField(max_lenght=100)
def get_tiny_object():
pass
def get_big_object():
pass
class Picture(Media):
picture = models.ImageField()
def get_tiny_object():
return ...
...
class Video(Media):
video = models.CharField(max_length=200) #youtube id
...
class Music(Media):
music = ....
You get the idea. ¿Does this work? Should I also record on "Something" what kind of media it is?
EDIT:
The idea behind having a Media class, is that I can render in the templates without knowing which kind of media I´m rendering. get_tiny_object() should return, if it is a picture:
"<img style="width:60px; height: 50px" ...>"
So if I have a foreign key to a media object lets say it's id=4, does django know that it should be fetched from music table, if the object I associated with is of Music kind? Because I´ll have 3 different id=4, one on each table (picture, video and music (and possibly more if the domain changes)).
I still think the question is a little hard to understand - the title is Database modelling in Django after all...However, this is a perfectly valid and reasonable thing to do, and seems to fit your intent:
The recommended way to do this is multi table inheritance - example:
class Media(models.Model):
pass
class Something(models.Model):
media = models.ForeignKey(Media)
class Picture(Media):
foo = models.CharField(max_length=100)
def get_tiny_object(self):
return self.foo
class Video(Media):
bar = models.CharField(max_length=100)
def get_tiny_object(self):
return self.bar
picture = Picture.objects.create(foo='some picture')
video = Video.objects.create(bar='some video')
something1 = Something.objects.create(media=picture)
something2 = Something.objects.create(media=video)
print something1.media.get_tiny_object() # this is a picture remember?
print something2.media.get_tiny_object() # and lo, here is a video
http://docs.djangoproject.com/en/dev/topics/db/models/#one-to-one-relationships
this says you should use a OneToOneField relating each Picture, Video, Music to a Media entry, and they all inherit directly from models.Model.
Also, you need to change your Something to
class Something(models.Model):
media = models.ForeignKey("Media")
because since Media isn't defined when you define Something (if you place it below it), it won't work, django provides you with the possibility of doing this with the classname instead of a reference to the class

Categories