How to show only user uploads django - python

How do I go by showing only user files that they upload (not all) I'm using python 2.7 and django 1.7 with django allauth. Below is my model. If anyone can point me to the right direction thank you.
models.py
def hashed_uploads_dirs(instance, filename):
return os.path.join(instance.md5, filename)
class File(models.Model):
f = models.FileField(upload_to='.')
md5 = models.CharField(max_length=32)
created_at = models.DateTimeField(auto_now_add=True)
def was_published_recently(self):
return self.created_at >= timezone.now() - datetime.timedelta(days=1)
was_published_recently.admin_order_field = 'created_at'
was_published_recently.boolean = True
was_published_recently.short_description = 'Published recently?'
def __unicode__(self):
return self.f.name
#models.permalink
def get_absolute_url(self):
return ('file-add', )
def save(self, *args, **kwargs):
self.slug = self.file.name
super(File, self).save(*args, **kwargs)
def delete(self, *args, **kwargs):
"""delete -- Remove to leave file."""
self.file.delete(False)
super(File, self).delete(*args, **kwargs)

You need to modify your file class to store a foreign key to a user. It should look like
...
from django.contrib.auth.models import User
class File(models.Model):
f = models.FileField(upload_to='.')
md5 = models.CharField(max_length=32)
created_at = models.DateTimeField(auto_now_add=True)
user = models.ForeignKey(User, related_name='uploaded_files')
...
When you upload the file, you'll also have to set the user before saving the file. Then when you have an instance of User you can get all the uploaded files with user.uploaded_files.

Create a new field in File:user = models.ForeignKey(User)
Then you can do
file.user = request.user
file.save()
in the function that handles the file upload

Related

Django createView passing current user_id to Modelform

I am trying to make a calendar app and currently trying to stop people from being about to save an event when they are already busy during that time period. I believe my issue is that the modelForm doesn't have the user_id as part of the form object. how can I pass the user_id so I can use it to filter with the clean().
I tried using get_form_kwargs() but this doesn't seem to be the correct route to take.
Please can you point me in the right direction of how to do this.
view.py
class CalendarEventAdd(LoginRequiredMixin, CreateView):
model = Event
form_class = EventForm
template_name = 'calendar_create_event_form.html'
success_url = reverse_lazy('calendar_list')
def form_valid(self, form):
form.instance.manage = self.request.user
return super(CalendarEventAdd, self).form_valid(form)
def get_form_kwargs(self, *args, **kwargs):
kwargs = super(CalendarEventAdd, self).get_form_kwargs()
kwargs['user_id'] = self.request.user
return kwargs
form.py
class EventForm(forms.ModelForm):
class Meta:
model = Event
widgets = {
'start_time': DateInput(attrs={'type': 'datetime-local'}, format='%Y-%m-%dT%H:%M'),
'end_time': DateInput(attrs={'type': 'datetime-local'}, format='%Y-%m-%dT%H:%M'),
}
fields = ['avilibility','start_time','end_time']
def __init__(self, *args, **kwargs):
super(EventForm, self).__init__(*args, **kwargs)
# input_formats parses HTML5 datetime-local input to datetime field
self.fields['start_time'].input_formats = ('%Y-%m-%dT%H:%M',)
self.fields['end_time'].input_formats = ('%Y-%m-%dT%H:%M',)
def clean(self, *args, **kwargs):
form_start_time = self.cleaned_data.get('start_time')
form_end_time = self.cleaned_data.get('end_time')
form_manage_id = self.cleaned_data.get('manage_id')
between = Event.objects.filter(manage_id=1, end_time__gte=form_start_time, start_time__lte=form_end_time)
if between:
raise forms.ValidationError('Already Calendar entry for this time')
super().clean()
model.py
class Event(models.Model):
avilibility_choices = [
('Avilible', 'Avilible'),
('Busy', 'Busy'),
]
id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
manage = models.ForeignKey(get_user_model(), on_delete=models.CASCADE)
avilibility = models.CharField(max_length=10, choices=avilibility_choices, editable=True)
start_time = models.DateTimeField()
end_time = models.DateTimeField()
def __str__(self):
return self.avilibility + " - " + str(self.start_time) + " - " + str(self.end_time) + " - " +str(self.id)
def get_absolute_url(self):
return reverse('calendar_event_detail', args=[str(self.id)])
def get_absolute_url_edit(self):
return reverse('calendar_event_detail_update', args=[str(self.id)])
def get_html_url(self):
url = reverse('event_edit', args=(self.id,))
return f' {self.avilibility} '
In your view, you should pass the primary key of the user, so:
def get_form_kwargs(self, *args, **kwargs):
kwargs = super(CalendarEventAdd, self).get_form_kwargs()
kwargs['user_id'] = self.request.user.pk
return kwargs
You can save it in the EventForm object:
class EventForm(forms.ModelForm):
def __init__(self, *args, user_id=None, **kwargs):
super(EventForm, self).__init__(*args, **kwargs)
self.user_id = user_id
# input_formats parses HTML5 datetime-local input to datetime field
self.fields['start_time'].input_formats = ('%Y-%m-%dT%H:%M',)
self.fields['end_time'].input_formats = ('%Y-%m-%dT%H:%M',)
def clean(self, *args, **kwargs):
form_start_time = self.cleaned_data.get('start_time')
form_end_time = self.cleaned_data.get('end_time')
form_manage_id = self.cleaned_data.get('manage_id')
between = Event.objects.exclude(pk=self.instance.pk).filter(
manage_id=self.user_id,
end_time__gte=form_start_time,
start_time__lte=form_end_time
)
if between.exists():
raise forms.ValidationError('Already Calendar entry for this time')
return super().clean()
The .exclude(pk=self.instance.pk) will exclude the object you are editing, if you later decide to use the EventForm not only to create but also update an Event object.
Note: The documentation advises to
use the AUTH_USER_MODEL setting [Django-doc] over
get_user_model() [Django-doc].
This is safer, since if the authentication app is not yet loaded, the settings
can still specify the name of the model. Therefore it is better to write:
from django.conf import settings
class Event(models.Model):
# …
manage = models.ForeignKey(
settings.AUTH_USER_MODEL,
on_delete=models.CASCADE
)

Why my edit form not updating data, but able to create new instance. I try every thing on google but still not working

I have a form for creating the object, and it works fine. When I use that form for editing the object, it doesn't work. I did debugging the post method,and it also works fine, the form is valid, the redirect work, the success message appear, but not update the object. The form instance is also work correctly. It just don't update
# models.py
class Item(models.Model):
status_choices = (
('rent','Rent'),
('give', 'Give'),
('share','Share'),
)
item_types = (
('book','Book'),
('movie','Movie',),
('data','Data'),
('other','Other'),
)
title = models.CharField(max_length=200, db_index=True)
slug = models.SlugField(max_length=200, db_index=True, blank=True,unique=True)
owner = models.ForeignKey(settings.AUTH_USER_MODEL)
cover = models.ImageField(upload_to='items/%Y/%m/%d',blank=True)
link = models.URLField(blank=True)
description = models.TextField(max_length=500, blank=True)
status = models.CharField(max_length=10,choices=status_choices,default='Share')
item = models.CharField(max_length=10, choices=item_types,default='Data', verbose_name='Item Type')
publish = models.DateTimeField(auto_now=True,null=True)
class Meta:
ordering = ('-publish',)
index_together = (('id', 'slug'),)
def __str__(self):
return '{} : <{}> for {}'.format(self.title,self.item,self.status)
def save(self, *args, **kwargs):
if not self.slug:
self.slug = slugify(self.title)
super(Item, self).save(*args, **kwargs)
def get_absolute_url(self):
return reverse('item_edit', kwargs={'slug':self.slug})
#forms.py
class ItemShareForm(forms.ModelForm):
class Meta:
model = Item
fields = ('title', 'cover', 'link', 'description', 'status', 'item')
widgets = {
'description' : forms.Textarea(),
}
#views.py
#login_required
def item_edit(request,slug):
instance = get_object_or_404(Item,slug=slug)
if request.method == 'POST': #check the request method
edit_form = ItemShareForm(request.POST ,instance=instance)
if edit_form.is_valid(): # check the form validation
update_item = edit_form.save(commit=False)
update_item.owner = request.user #assign the owner
update_item.save() # update the instance
messages.success(request,'Your item has been updated successfully') # writing the message to user
return redirect('/')
else:
messages.error(request,'Error updating your item...')
else:
edit_form = ItemShareForm(instance=instance)
return render(request, 'account/share.html',{'itemform':edit_form})*
You have overridden you model save method like so:
def save(self, *args, **kwargs):
if not self.slug:
self.slug = slugify(self.title)
super(Item, self).save(*args, **kwargs)
This means that the object will only ever get saved if the slug is empty - i.e., it will only ever get saved once. Any future calls to save will not execute that if block, and nothing will happen.
You probably mean to do this instead - note indentation of the last line:
def save(self, *args, **kwargs):
if not self.slug:
self.slug = slugify(self.title)
super(Item, self).save(*args, **kwargs)

Final FormWizard redirects to first step

I basically used the django-formtool form wizard to handle saving of my form.
User enters the "username" and "repository" on first step.
repository is cloned
User enters "inventory" and "user" on second step.
I'm expecting that after the final submit, it will just save the data
I'm having trouble when I try to save on the final step of the wizard,
I returns me to the first step. With the expected ValidationError that the repository exists, because on my views.py execute the clone_repository() method.
Below are the relevant code I currently have.
views.py
class PlaybookWizard(SessionWizardView):
def process_step(self, form):
if self.steps.current == '0':
form.clone_repository()
if self.steps.current == '1':
form.save()
return super(PlaybookWizard, self).process_step(form)
def done(self, form_list, form_dict, **kwargs):
return HttpResponseRedirect('/playbooks')
forms.py
def check_path_exists(repository, host_inventory=None):
if host_inventory:
os.chdir(settings.PLAYBOOK_DIR + repository)
current_dir = os.getcwd()
return os.path.exists(os.path.join(current_dir, host_inventory))
return os.path.exists(os.path.join(settings.PLAYBOOK_DIR, repository))
def get_dir_name(repository):
return os.path.join(settings.PLAYBOOK_DIR, repository)
def get_remote_repo_url(username, repository):
return "https://github.com/{0}/{1}.git".format(
username, repository
)
class AnsibleForm1(ModelForm):
class Meta:
model = Playbook
fields = ['repository', 'username']
def clean_repository(self):
if check_path_exists(self.cleaned_data['repository']):
raise ValidationError("Repository already exists")
return self.cleaned_data['repository']
def clone_repository(self):
repository = self.cleaned_data['repository']
username = self.cleaned_data['username']
dir_name = get_dir_name(repository)
remote_url = get_remote_repo_url(username, repository)
os.mkdir(os.path.join(dir_name))
repo = git.Repo.init(dir_name)
origin = repo.create_remote('origin', remote_url)
origin.fetch()
origin.pull(origin.refs[0].remote_head)
class AnsibleForm2(ModelForm):
class Meta:
model = Playbook
fields = ['inventory', 'user']
models.py
class Playbook(models.Model):
username = models.CharField(max_length=39, default="")
repository = models.CharField(max_length=100, default="")
inventory = models.CharField(max_length=200, default="hosts")
user = models.CharField(max_length=200, default="ubuntu")
directory = models.CharField(max_length=200, editable=False, default="dir")
def get_dir_name(self):
return os.path.join(settings.PLAYBOOK_DIR, self.repository)
def format_directory(self):
directory = self.repository.lower()
directory = directory.replace(" ","-")
return directory
def save(self, *args, **kwargs):
self.directory = self.format_directory()
super(Playbook, self).save(*args, **kwargs)

Media files not being returned properly

models.py:
class FWVersion(models.Model):
bin_file = models.FileField(upload_to='fW_media/bin/')
date_created = models.DateTimeField(default=timezone.now)
name = models.CharField(max_length=64)
serializers.py:
class UploadFWSerializer(serializers.ModelSerializer):
class Meta:
model = FWVersion
exclude = ('date_created',)
class GetFWSerializer(serializers.ModelSerializer):
class Meta:
model = FWVersion
fields = ('name', 'bin_file',
)
views.py:
class GetFWView(viewsets.ModelViewSet):
queryset = FWVersion.objects.all()
serializer_class = serializers.GetFWSerializer
def get_object(self):
lastest_fw = FWVersion.objects.first()
return lastest_fw
class UploadFWView(mixins.CreateModelMixin,
generics.GenericAPIView):
serializer_class = serializers.UploadFWSerializer
def post(self, request, *args, **kwargs):
return self.create(request, *args, **kwargs)
I am using django-rest-framework to create APIs for uploading and retrieving the latest version of the .bin file. The APIs are working and I am able to upload a .bin file on the server. But when downloading the file again, the server returns the first uploaded file(the oldest one)even though the name, url are of the latest uploaded file. Sometimes rarely however, it returns the latest file. I have checked the server files, they are being uploaded properly. Is this because of some caching by Django or am I missing something? Please help.
Your code pretty clearly calls first() on the queryset in GetFWView, so I'm not sure why this behaviour surprises you. If you want to always return the latest one, then you should do that:
def get_object(self):
lastest_fw = FWVersion.objects.latest('date_created')
As an aside, you shouldn't be using a ViewSet for that view; it only supports one operation, which is GET, so you should just use a RetrieveAPIView.
def get_attachment_path(instance, filename):
ext = os.path.splitext(filename)[1]
d = os.path.dirname(filename)
current_time = datetime.now().strftime('%Y%m%d-%H%M%S-%f')[:-3]
filename = os.path.join(d, current_time + ext)
return 'fW_media/bin/{}'.format(filename)
class FWVersion(models.Model):
bin_file = models.FileField(upload_to=get_attachment_path)
name = models.CharField(max_length=64)
create_time = models.DateTimeField(auto_now_add=True)
class GetFWView(viewsets.ModelViewSet):
queryset = FWVersion.objects.all()
serializer_class = GetFWSerializer
def create(self, request, *args, **kwargs):
serializer = UploadFWSerializer(data=request.data)
if serializer.is_valid():
instance = serializer.create(serializer.validated_data)
return Response('upload success')
else:
return Response(serializer.errors)
#list_route(methods=['GET'])
def get_latest(self, request):
lastest_fw = FWVersion.objects.latest('create_time')
serializer = self.get_serializer(lastest_fw)
return Response(serializer.data)

Django call a funtion in model save method and call another function to fill value

I have a model in Django
class File(models.Model):
NORMAL = 'normal'
AD = 'ad'
FILE_TYPE_CHOICES = (
(NORMAL, 'Normal'),
(AD, 'Ad'),
)
file_name = models.CharField(max_length=50)
file_type = models.CharField(max_length=10, default=NORMAL,
choices=FILE_TYPE_CHOICES)
file_path = models.FileField('file', upload_to='documents/%Y/')
duration = models.IntegerField()
#prompt_id = models.CharField(max_length=50)
def __unicode__(self):
return self.file_name
def save(self, *args, **kwargs):
self.prompt_id = IvrUploadAudioFile(self.file_path)
super(File, self).save(*args, **kwargs)
i have a column prompt_id in file table, but I don't want to show prompt_id field in add/edit.
i Want to insert prompt_id value, which a function IvrUploadAudioFile will return behind the scene. so i am overriding save method here.
so where to write IvrUploadAudioFile function.
how to write this situation
Django models are just normal Python classes, and you can add as many helper methods as you want to the class:
class File(models.Model):
# -- normal stuff
prompt_id = models.CharField(max_length=50, editable=False)
def ivr_upload_audio_file(self):
# do something with self.file_path
return something
def save(self, *args, **kwargs):
self.prompt_id = self.ivr_upload_audio_file()
super(File, self).save(*args, **kwargs)
As for your other question, about not showing the field - you can add editable=False to hide the field in the admin and any ModelForms - however, if you just want to hide it in the admin, but show it in other forms - you can customize your admin to not show that field:
#admin.register(File)
class FileAdmin(admin.ModelAdmin):
fields = ('file_name', 'file_path', 'file_type', 'duration',)
You can write it anywhere as long as it can be imported into your project.
from <insert_path_here> import IvrUploadAudioFile # Function written somewhere else. You need to insert the correct path here
from django.db import models
class File(models.Model):
NORMAL = 'normal'
AD = 'ad'
FILE_TYPE_CHOICES = (
(NORMAL, 'Normal'),
(AD, 'Ad'),
)
file_name = models.CharField(max_length=50)
file_type = models.CharField(max_length=10, default=NORMAL,
choices=FILE_TYPE_CHOICES)
file_path = models.FileField('file', upload_to='documents/%Y/')
duration = models.IntegerField()
#prompt_id = models.CharField(max_length=50, editable = False)
def __unicode__(self):
return self.file_name
def save(self, *args, **kwargs):
self.prompt_id = IvrUploadAudioFile(self.file_path)
super(File, self).save(*args, **kwargs)
To make sure that the prompt_id field is not editable in the admin view, set the editable = False attribute when defining the prompt_id field in the model.
If you're talking about wanting to hide the field in Django admin, you need to set it as editable=False: https://docs.djangoproject.com/en/1.7/ref/models/fields/#editable
class File(models.Model):
. . .
prompt_id = models.CharField(max_length=50, editable=False)
I'm not sure what you intend to do by passing self.file path to your IvrUploadAudioFile class, but the code, as written, will not return the primary key of that object.

Categories

Resources