getting Django current user on iOS app - ios

I'm new to Django, I'm starting a Django app, I'm using the registration app and Django rest framework, this app will also serve as the backend for an iOS app, I already manage to create users from the iOS app and edit User Profiles from the browser, I need help to find an approach that lets the user edit his profile details once he is logged in. I tried setting a lookup_field like "user.username" to the UserProfileViewSet so I could access the UserProfile object and edit it, but that didn't work.
I also thought I could somehow return the user id after logging in and use this id to reference the userprofile I wanna edit but it does not seem practical at all. What do you think??
Other way I found to do this is by calling user.get_profile() but I don't know how I can make this work from the iOS app.
Here is my UserProfile Model, and serializers, any help would be great. Thanks
class UserProfile(models.Model):
user = models.OneToOneField(User, unique=True)
# Extra attribuets
pagetitle = models.TextField(null=False)
location = models.TextField(null=True)
website = models.TextField(null=True)
bio = models.TextField(null=True)
sex = models.TextField(null=True)
birthdate = models.DateField(null=True)
def __unicode__(self):
return "%s's profile" % self.user
def create_profile(sender, instance, created, **kwargs):
if created:
profile, created= UserProfile.objects.get_or_create(user=instance)
post_save.connect(create_profile, sender=User)
class UserSerializer(serializers.HyperlinkedModelSerializer):
class Meta:
model = User
fields = ('username','email','password')
class UserProfileSerializer(serializers.HyperlinkedModelSerializer):
user = UserSerializer(many=False)
class Meta:
model = UserProfile
fields = ('user','bio')
I create the UserProfile using a signal like this
def create_profile(sender, instance, created, **kwargs):
if created:
profile, created= UserProfile.objects.get_or_create(user=instance)
post_save.connect(create_profile, sender=User)

You didn't post your ViewSet code, so I have to guess. But your model should be set to User and your lookup_field should be set to username.
Something like:
class UserViewSet(ModelViewSet):
model = User
lookup_field = "username"

For everyone trying to get the profile for a user this is the way I managed to do it thanks to Kevin's help.
class UserSerializer(serializers.HyperlinkedModelSerializer):
class Meta:
model = User
depth = 1
fields = ('id','username','email','profile')
class CurrentUserView(APIView):
def get(self, request):
serializer = UserSerializer(request.user)
return Response(serializer.data)
Using a url like this
url(r'^api/current-user',CurrentUserView.as_view(),
name="current_user"),
You will get an answer like this
"id": 1,
"username": "username",
"email": "email#email.com",
"profile": {
"id": 1,
"user": 1,
"bio": "My Bio",
"sex": "M",
"birthdate": "1987-12-02"
}

Related

I'm trying to change the standard django registration using crispy-forms, but at the same time the registration confirmation email stops coming

Installed crispy-forms and configured templates for authentication. Everything works well. Problem with registration. With the standard registration form, I fill out the forms, then an email is sent to the mail confirming registration with a link to activate the account. But as soon as I try to implement the crispy-forms template, the letter stops coming and immediately throws it to the login form. How do I make emails arrive using crispy-forms?
I tried a lot of things but there is no result
forms.py
your
class SignUpForm(UserCreationForm):
email = forms.EmailField(label="Email")
first_name = forms.CharField(label="Имя")
last_name = forms.CharField(label="Фамилия")
class Meta:
model = User
fields = (
"username",
"first_name",
"last_name",
"email",
"password1",
"password2",
)
text
views.py
`your
class SignUpView(CreateView):
model = User
form_class = SignUpForm
success_url = reverse_lazy('login')
template_name = 'registration/signup.html'
success_message = "Ваш профиль создан"
texturls.pyyour
urlpatterns = [
path("signup/", SignUpView.as_view(), name='signup'),
path("update/<int:pk>", AccountUserUpdate.as_view(), name='account_update'),
path('setauthor/', set_me_author, name='set_me_author'),
path('login/', views.LoginView.as_view(), name='login'),
path('logout/', views.LogoutView.as_view(), name='logout'),
path('password-change/', views.PasswordChangeView.as_view(), name='password_change'),
path('password-change/done/', views.PasswordChangeDoneView.as_view(), name='password_change_done'),
path('password-reset/', views.PasswordResetView.as_view(), name='password_reset'),
path('password-reset/done/', views.PasswordResetDoneView.as_view(), name='password_reset_done'),
path('reset/<uidb64>/<token>/', views.PasswordResetConfirmView.as_view(), name='password_reset_confirm'),
path('reset/done/', views.PasswordResetCompleteView.as_view(), name='password_reset_complete'),
text`

Rails how to save data upon creation with an external API?

In my app for bike_rental_shops, I'm making it possible for these shops to manage their bike rentals.
Context
Bike rental companies also offer their bikes on website of external parties, therefore I'm connecting my Rails application with these external websites. I'm currently handling this in my controller when a user goes to the index page. Before loading the index page an API call is made to the external rental website and new bike rentals should be saved in the database.
Question
How to save only new rentals and not all rentals linked to a certain external rental website?
Current consideration
The only thing I can come up with is adding a database column with {external_website}_rental_id for a specific external website, so I can match them. However, this would mean that I need to add a seperate rental_id for every external rental website.
Code
rentals_controller.rb
def index
shop = Shop.find(params[:id])
request_rental_api
#bikes = shop.bikes
end
private
def request_rental_api
# set variables
base_url = "https://www.rentalwebsite.com"
url = "/rest/api/rentals"
token = 'TOKEN'
# init connection object
connection = Faraday.new(:url => base_url) do |c|
c.use Faraday::Request::UrlEncoded
c.use Faraday::Response::Logger
c.use FaradayMiddleware::FollowRedirects
c.adapter Faraday::Adapter::NetHttp
end
# send request
response = connection.get url do |request|
request.headers["Authorization"] = token
request.headers["Accept"] = "application/json"
end
bookings = JSON.parse(response.body['results'])
# check if rental is unique, and if so save it.
# Rental.create(????)
end
JSON output API
{
"next": null,
"previous": null,
"results": [
{
"activation_requested": false,
"id": 21664,
"slug": "rental-test"
#more information....
}
}]
you can create 2 columns
provider_rental_id id returned in response JSON
provider name of provider, to which request was made
Then to only create new records
rental_ids = bookings['results'].map { |r| r['id'] }
return if rental_ids.none?
existing_rental_ids = Rental.where(provider_rental_id: rental_ids, provider: 'Name of Provider').pluck(:provider_rental_id)
new_rental_ids = rental_ids - existing_rental_ids
new_rental_ids.each do |rental_id|
Rental.create(
provider: 'Name of Provider',
provider_rental_id: rental_id,
...
or if you are using rails 6 you can check upsert_all
Note: It does not instantiate any models nor does it trigger Active Record callbacks or validations.
Additionally try to move this into a background cronjob

How to access to the company name into an email in rails?

I'm currently trying to use the company name present into an email. But I don't find a simple way to access to. And ask i there is others.
An example is better than explanation :
User.new (mail) => user#company1.com
--> That the value that I want to catch <--
==> #company = company1
if Company.where(name: #company).any?
render show #company
else
reder new Company
end
So if you have any solutions to access to that, you'll be my hero !
Thanks for your time
I'm not an expert on rails, but you can try this :
#pars1 = #company.split('#')
#pars2 = #pars[1].split('.')
#pars3 = #pars[0]
=> company
Try to read that, it can be useful :
How can you return everything after last slash(/) in a Ruby string

Custom Admin View and User Restriction

I want to create a custom view in django admin that mirrors a change form from another model. I've got as far as creating a custom model admin class, and don't know where to go from here. I cant find any good examples for Django 1.8 on how to create a custom admin view.
Django Version: 1.8
class CustomerProductOrderAdmin(admin.ModelAdmin):
review_template = 'admin/onlineordering/order_template.html'
def get_urls(self):
urls = super(CustomerProductOrderAdmin, self).get_urls()
my_urls = patterns('',
(r'\d+/customer_template/$', self.admin_site.admin_view(self.customer_template)),
)
return my_urls + urls
def customer_template(self, request, id):
product_orders = CustomerProductOrder.objects.get(pk=id)
return render_to_response(self.review_template, {
'quantity': 'Quantity: %s' % product_orders.quantity,
}, context_instance=RequestContext(request))
I have a customer table that belong to this user table.
class Customer(models.Model):
customer = models.ForeignKey(settings.AUTH_USER_MODEL, limit_choices_to={'groups__name': "customers"})
/app/model/1 #pk = customer.id
The custom form will have this URL
/app/customform/
When the logged in user goes to /app/customform, they should not see the change form from /app/model/1. They should not see other users change forms. Also, I would like to limit access to the custom form, to a particular group of users. ie this group cannot see /app/model/ but can see /app/customform.
An example for how to add an independent template to admin page
At the model.py file inside the model class add a function
def version_summery(self, ):
batch_d= {}
fy = {}
for br in self.batchresult_set.all():
batch_d[br.name.strip()] = br.__dict__
fy['batch_d'] = batch_d.values()
x = render_to_string('admin/results/result_build_summary.html', fy)
return x
make sure the urls.py knows how to find the template 'result_build_summary.html'
and in the admin.py
readonly_fields = ( 'version_summery',)
fieldsets = (
('', {
'fields': ( 'version_summery', ),
}),
)

Odd behaviour when extending an object with a module in ruby

If I do the following:
user = User.new
user.extend Customer
user.is_a? Customer == true
it works fine.
However if I do the following (where Profile is a mongoid model and user is embedded):
profile = Profile.all.first
profile.user.extend Customer
profile.user.is_a? Customer == false
user is no longer a customer. There must be a simple reason for this but I can't see it.
Edit: User and Profile are mongoid Models, ie. profile.user.class = User and profile.class = Profile.
My guess: every time you call profile.user you are getting a new object. Try:
2.times{ p profiler.user.object_id }
and see what happens. Then try:
u = profile.user
u.extend Customer
p u.is_a? Customer
p profile.user.is_a? Customer
and see what output you get.
This actually ended up being a bug in Mongoid. Here is the issue with description:
https://github.com/mongoid/mongoid/issues/1933
It is now fixed in the latest commit.

Resources