I am serving my Django-Wagtail media files trough Amazon S3 and now I reached a point where I need to define a customized Document Class which creates "restricted" documents (only accesible if you are logged). This documents will have a special access that will say to my S3 bucket "hey! just deliver this files If they are requested from this "foo_url" but not from anywhere else", since they will be shown to logged users only. I thought of this to prevent restricted urls to spread out.
That's why I am trying to define this Wagtail Document class to be stored in a subfolder of /documents/ and just tell Amazon what to do with that subfolder.
dummy_code_that_doesnt_work:
class RestrictedDocument(Document):
def get_upload_to(self, filename):
folder_name = 'restricted'
filename = self.file.field.storage.get_valid_name(filename)
return os.path.join(folder_name, filename)
"""
Snippet containing restricted documents
"""
#register_snippet
#python_2_unicode_compatible # provide equivalent __unicode__ and __str__ methods on Python 2
class FooSnipet(models.Model):
rectricted_document_1 = models.ForeignKey(
'RestrictedDocument',
null=True,
blank=True,
on_delete=models.SET_NULL,
related_name='+',
)
rectricted_document_2 = models.ForeignKey(
'RestrictedDocument',
null=True,
blank=True,
on_delete=models.SET_NULL,
related_name='+',
)
....
and many more
....
Maybe I am overcomplicating all this and there is another way of doing. Any suggestion will be super welcome! Thank you veeery much :)
The Document model doesn't support a get_upload_to method like images do. However, as of Django 1.10 it's possible to override the file field of AbstractDocument:
from wagtail.wagtaildocs.models import AbstractDocument
class RestrictedDocument(AbstractDocument):
file = models.FileField(upload_to='restricted', verbose_name=_('file'))
I'm not sure that this will help much, though - the views in the Wagtail admin that handle document uploads have no way of knowing that they should save the document through the RestrictedDocument model, rather than the default Document class.
Implementing view restrictions on documents within Wagtail is currently a work in progress (https://github.com/wagtail/wagtail/pull/3245, https://github.com/wagtail/wagtail/issues/1420).
Related
Is there anyway where we can build logic Using django rest framework
where user can add blog with multiple images and content accordingly and when saved
and retrieved it should be able to display the same kind of UI depening up on the frontend app
same like medium platform
Note:
My question isn't about adding multiple images and content using Rest framework
but its about fetching and displaying the data based on how user sent it the server
For eg:
<Image>
content for that image
<Image2>
content for this image
i just want to know how to associate those images to that content
i want to add content to that image
or is there anyway where we can store image and all the content exacty and save it in TextField
I've searched a lot about this but unfortunately I've not found a way to make this happen
Read about relationships in Django (and SQL in general)
django relations
it sounds like you're looking for something like the following:
from django.contrib.auth import get_user_model
from django.contrib.auth.models import AbstractUser
from django.db import models
class CustomUser(AbstractUser):
# Always override the user model provided by Django when starting a project. the docs themselves state that.
pass
class Image(models.Model):
image = models.ImageField()
added = models.DateTimeField(auto_now_add=True)
# using get_user_model to get the User model, always better then referencing User directly
user = models.ForeignKey(get_user_model(), on_delete=models.CASCADE, related_name="user_images",
null=False,
blank=False
)
class ImageContent(models.Model):
title = models.CharField(max_length=140, null=False, blank=False)
content = models.TextField(max_length=500)
image = models.OneToOneField(Image, on_delete=models.CASCADE, null=False, blank=False)
Some notes:
I haven't dealt myself with Images field But I remember it does require a special library (pillow).
getting the data in a certain order should be easy enough if you understand the queryset object:
queryset link
using stuff like order_by will help you return the response in the order you like.
the models I've written here are not the only way to achieve the goal you've set, I strongly recommend reading about relations and models in Django.
I have a blog on django on which any public can post. In post content I am using django-ckeditor RichTextUploadingField.
There is button Browse server for images in ckeditor, that let users browse images of server's upload directory and embed images in post.
But i want to restrict public from browsing images on server when they make post. They should be able upload images only, not browse every image on server that is uploaded.
Here is my models.py
class Article(models.Model):
title = models.CharField(max_length = 200)
content = RichTextUploadingField()
author = models.ForeignKey(User, on_delete= models.CASCADE, null=True)
def __str__(self):
return self.title
Forms.py
class ArticleForm(ModelForm):
class Meta:
model = Article
widgets = {
'content': RichTextUploadingField()
}
A direct setting to remove this functionality isnt provided but CKEDITOR_RESTRICT_BY_USER = True could be used to achieve the same.
Reference from the documentation:
Set the CKEDITOR_RESTRICT_BY_USER setting to True in the project's
settings.py file (default False). This restricts access to uploaded
images to the uploading user (e.g. each user only sees and uploads
their own images). Upload paths are prefixed by the string returned by
get_username. If CKEDITOR_RESTRICT_BY_USER is set to a string, the
named property is used instead. Superusers can still see all images.
NOTE: This restriction is only enforced within the CKEditor media
browser.
I need some help in understanding how to implement a photo upload in 2 different app and keeping my project DRY. I have an app (gallery) where I defined 3 different view (it's practically an implementation of django-jquery-file-upload example in git: https://github.com/sigurdga/django-jquery-file-upload)
class PictureCreateView(CreateView)
...
class PictureDeleteView(DeleteView):
...
class PictureListView(ListView):
...
This 3 class are used in the same template to choose multiple photo to upload (and eventually delete) to the server. Everything works fine within the gallery app but now I'd like to use all there 3 views in 2 different app (and models). The gallery models is the following:
class Picture(models.Model):
file = models.ImageField()
place = models.ForeignKey(
'app_place.Poi',
related_name='places',
null=True, blank=True,
)
event = models.ForeignKey(
'app_event.Event',
related_name='events',
null=True, blank=True,
)
So that each photo could be related to an event (or place). I'd like to use the 3 views from the gallery app in the event and place DetailView (all authenticated users can add photo to places or events) which belongs to 2 different apps... what is the correct approach? Trying to define the 3 gallery views as mixin? Or call them using the get_context_data? I don't know how to proceed and nay help/suggestion is wellcome
I would love to have more granular permission in my Django project, but can't decide what app to use.
What I have is something like:
class Item(models.Model):
name = models.CharField(max_length=64, unique=True)
description = models.CharField(max_length=128, default='')
logo = ImageField(upload_to=/tmp, blank=True, null=True)
Now with Django standard permissions I have the possibility to choose between add, change and delete, what I want to have is an extended change permission, to offer the ability to give group rights only to change the logo for example, but disallow that same group to modify the item description. I don't want or need a user to entry relation, but simply give the possibility to different groups to edit single fields of a model using the standard admin interface. I'm even not sure if I am talking about per-object permission?
Does anyone know what's best to use or how I would implement it myself? I could also imagine to have read-only users who can access/read everything but won't be able to modify, this isn't possible neither.
Thanks for any help.
The most flexible but way would be to:
write some custom permissions (i.e. can_modify_descr)
write yur own Forms or ModelForms
write Views to render your specified forms.
finally you'd have to override some django admin templates and render your Forms in templates that extend some standard django admin templates.
As far as I can see this is the only way to achieve what you want, but also requires a lot of work.
One simple way to achieve that is to create many ModelAdmin for the same model (one for each "group"). To do that you need to create one Proxy Models for each "group" like this:
models.py
class Item(models.Model):
name = models.CharField(max_length=64, unique=True)
description = models.CharField(max_length=128, default='')
logo = ImageField(upload_to=/tmp, blank=True, null=True)
class ItemGroup1(Item):
class Meta:
proxy = True
admin.py
class ItemAdmin(models.ModelAdmin):
...
class ItemGroup1Admin(models.ModelAdmin):
readonly_fields = ('logo', 'description')
And then you just need to set the permissions of group 1 to only have access to ItemGroup1, etc.
See this post for more info: Using Proxy Models to Customize the Django Admin
If you want to handle this sort of thing beyond your admin site, take a look at django-logical-rules, where you can write your rules in python and access them from views or within a template;
I'm trying to create a field in a model, that should store an image for a registered user.
This image should be renamed and stored in a separate user directory like media/users/10/photo.jpeg.
I've searched a lot, but still can't find how to do it cleanly and correctly. It seems to me that many sites require the same functionality and this should be in django docs, but it is not.
You want to use the "upload_to" option on an ImageField
#models.py
import os
def get_image_path(instance, filename):
return os.path.join('photos', str(instance.id), filename)
class UserProfile(models.Model):
user = models.ForeignKey(User, unique=True)
profile_image = ImageField(upload_to=get_image_path, blank=True, null=True)
This is code directly from a project of mine. The uploaded image goes to /MEDIA_ROOT/photos/<user_id>/filename
For what you want, just change the 'photos' string to 'users' in def get_image_path
Here is the small bit about it in the docs, under FileField details
I suggest you to look into django-photologue. Its a django app with all image managment, uploading and storing already done!
More about at: http://code.google.com/p/django-photologue/
You'll need to make a model that has a foreign key to the User model, where you can have an image field for the User. I would not recommend modifying the User model itself.