How to save a raster in RasterField after save in GeoDjango? - django

I am building an app using Django with PostGIS backend. Thus, GeoDjango. I have a model with FileField, and RasterField [1]. I want to save a raster object to RasterField after supplying the FileField. I am trying to achieve this using a post_save signal.
class Layer(models.Model):
name = models.CharField(max_length=50, blank=True)
file = models.FileField(
upload_to='layers',
null=True,
max_length=500)
raster_file = RasterField(
null=True,
blank=True,
)
After some research [2], you have to use GDALRaster [3] to make the raster as an object. In my signals:
from django.contrib.gis.gdal import GDALRaster
from data_management.models import Layer
#receiver(post_save, sender=Layer)
def create_raster(sender, instance, **kwargs):
instance.raster_file = GDALRaster(instance.file.path)
instance.save()
When I am uploading the file in my admin, the raster_file is not filled and not created. How do I save the raster, which is uploaded through the file field, in my raster_file field?

Related

Django delete multiple ImageField files on model delete

I have an Image model with two ImageFields (one for regular image and one for the thumbnail). I'm trying to delete both files together with a post_delete receiver but I'm having difficulty chaining the operations.
What I have throws a file does not exist error probably because only one delete saves.
class Image(models.Model):
path = models.ImageField(upload_to=photo_image_upload_path,blank=False, null=False)
thumb = models.ImageField(upload_to='', editable=False, default=None, null=True)
#receiver(post_delete, sender=Image)
def photo_delete(sender, instance, **kwargs):
# Pass false so FileField doesn't save the model.
if instance.thumb is not None:
instance.thumb.delete(True)
if instance.path is not None:
instance.path.delete(False)

Using callable as path attribute of Django's FilePathField?

I have the following model that includes a file upload by a user.
def resume_path(instance, filename):
# file will be uploaded to MEDIA_ROOT/user_<id>/resume/<filename>
return 'user_{0}/resume/{1}'.format(instance.student_user.id, filename)
class Resume(models.Model):
resume = models.FileField(upload_to=resume_path, blank=True, null=True)
pub_date = models.DateTimeField(default=timezone.now)
student_user = models.ForeignKey(User, on_delete=models.CASCADE, null=True)
Then, I would like to allow a user to select one of their uploaded files in a later form. So, I need to be able to dynamically set the path to the directory containing that user's files similar to the dynamic way that I set the upload_path in the original model.
I've tried the following according to this link:
def resume_directory_path(instance):
# returns the path: MEDIA_ROOT/user_<id>/resume/
return 'user_{0}/resume/'.format(instance.student_user.id)
class JobApplication(models.Model):
student_user = models.ForeignKey(StudentUser, on_delete = models.CASCADE)
resume = models.FilePathField(path=resume_directory_path, null=True)
However, looking at the documentation for FilePathField in Django 3.0, it doesn't look like it takes a callable for the path attribute. So, I'm not sure how the answer in the above link answers my question. What is the best way to achieve this functionality?
I'd like to do something like the below:
class CallableFilePathField(models.FilePathField):
def __init__(self, *args, **kwargs):
kwargs['path'] = resume_directory_path(instance)
super().__init__(*args, **kwargs)
class JobApplication(models.Model):
student_user = models.ForeignKey(StudentUser, on_delete = models.CASCADE)
resume = models.CallableFilePathField(path=resume_directory_path, null=True)
The trouble is that I don't know how to properly reference the model instance in this code (so instance is undefined). I've looked at the FileField code to try to see how they do it there, but I couldn't make sense of it.

django_filters picking up %(app_label)s_related_name as field name

(Django 1.8.14)
So I have one model, which uses a ContentType to point to a collections of models across separate apps.
I want to be able to "plug in" the functionality linking that model to the other models in the separate app. So we have the follwing:
class MyModelMixin(models.Model):
""" Mixin to get the TheModel data into a MyModel
"""
updated_date = models.DateTimeField(null=True, blank=True)
submission = GenericRelation(
TheModel,
related_query_name='%(app_label)s_the_related_name')
class Meta:
abstract = True
The main model model looks like this:
class TheModel(models.Model):
""" This tracks a specific submission.
"""
updated = models.DateTimeField()
status = models.CharField(max_length=32, blank=True, null=True)
final_score = models.DecimalField(
decimal_places=2, max_digits=30, default=-1,
)
config = models.ForeignKey(Config, blank=True, null=True)
content_type = models.ForeignKey(
ContentType,
blank=True,
null=True)
object_id = models.PositiveIntegerField(blank=True, null=True)
my_model_instance = GenericForeignKey()
And the mixin is included in the MyModel models, which are available in many different apps.
When using a filter for this, using django filters, there is an issue. I have a filter that's supposed to be instantiated to each app when it's used. However when I instantiate, for example, with
class MyFilterSet(Filterset):
def __init__(self, *args, **kwargs):
self.config_pk = kwargs.pop('config_pk', None)
if not self.config_pk:
return
self.config = models.Config.objects.get(pk=self.config_pk)
self.custom_ordering["c_name"] =\
"field_one__{}_the_related_name__name".format(
self.config.app_model.app_label,
)
super(MyFilterSet,self).__init__(*args, **kwargs)
However, when I use this, I get
FieldError: Cannot resolve keyword 'my_app_the_related_name field. Choices are: %(app_label)s_the_related_name, answers, config, config_id, content_type, content_type_id, final_score, form, form_id, id, object_id, section_scores, status, updated
How can %(app_label)s_the_related_name be in the set of fields, and how can I either make it render properly (like it does outside of django filters) or is there some other solution.
You have probably encountered issue #25354. Templating related_query_name on GenericRelation doesn't work properly on Django 1.9 or below.
Added in Django 1.10 was related_query_name now supports app label and class interpolation using the '%(app_label)s' and '%(class)s' strings, after the fix was merged.

Add custom user using django-allauth extra data

I would like to save data I get with allauth package after signing up using facebook.
I made a custom user :
class AppUser(models.Model):
birthdate = models.DateTimeField(null=True, blank=True)
address = adress_model.AddressField(null=True, blank=True)
image = models.ImageField(upload_to=get_image_path, blank=True, null=True)
gender = models.TextField(null=True, blank=True)
user = models.OneToOneField(User)
I would like to store all data in the database so I can easily access it from database.
P.S: If u can tell me how I can make a login page with button that will trigger it as well it would be great!
You can either use the save() method of the model to extract and save the data:
save(self, *wargs, **kwargs)
social_account = self.socialaccount_set.get(provider="facebook")
self.first_name = social_account.extra_data['first_name']
super(User, self).save(*wargs, **kwargs)
Or you can use the provided signal by allauth:
allauth.socialaccount.signals.social_account_added(request, sociallogin)
Check here for signal docs: http://django-allauth.readthedocs.io/en/latest/signals.html

Django FileField generate path based on ForeignKey record's slug field

This is for a game mod filesharing site. I have Apps Mods and Games. Each hold, you guessed it, Mods and Games!
Here is my Mods model:
from django.db import models
# Register storage backend TODO
def mod_directory_path(instance, filename):
# file will be uploaded to MEDIA_ROOT/<game>/<filename>
# Example code from https://docs.djangoproject.com/en/1.9/ref/models/fields/
return 'user_{0}/{1}'.format(instance.user.id, filename)
# Create your models here.
class Mods(models.Model):
title = models.CharField(max_length=30)
author = models.CharField(max_length=30)
game = models.ForeignKey(
'games.Games',
on_delete=models.CASCADE,
)
website = models.URLField()
repoWebsite = models.URLField()
upload = models.FileField(upload_to=mod_directory_path)
Here is my Games model:
from django.db import models
# Create your models here.
class Games(models.Model):
title = models.CharField(max_length=30)
developer = models.CharField(max_length=30)
website = models.URLField()
slug = models.SlugField()
I want to autoset the mod_directory_path to the slug of the Games model.
For example, if Mod item "Dynamic War Sandbox" has a ForeignKey of a unique ID pointing to the Arma 3 game, I want the file upload path to be based on the slug of the database entry for Arma 3.
MEDIA_ROOT/arma-3/<filename>.
How would I do this?
Something like this should work. The only requirement is that the game already exists in your database before the mod is being created.
def mod_directory_path(instance, filename):
slug = instance.game.slug
return os.sep.join([slug, filename])