def add_favorite_user(request, user_id=None): ''' 指定されたIDのユーザをログインユーザのフェイバリットに登録します。 指定IDのユーザを除くユーザだけが作成を行うことができます。(user!=request.user) JSONで返されるFavoriteUserインスタンスは以下の状態になっています。 user: ログインユーザ target: 指定されたIDのUserインスタンス @param user_id: ユーザID @return: 302レスポンス (ログインページへ。ログインしていない場合) @return: 403レスポンス (指定されたユーザがログインユーザの場合) @return: 404レスポンス (指定されたIDのユーザが存在しない場合) @return: 200レスポンス (成功。FavoriteUserインスタンスをJSONで出力) ''' target = get_object_or_404(User, pk=user_id) user_is_active_or_404(target) if target == request.user: return render_to_response_of_class(HttpResponseForbidden, '403.html') if not FavoriteUser.objects.reach_limit(request.user): try: fav = FavoriteUser.objects.get(user=request.user, target=target) except: fav = FavoriteUser.objects.create(user=request.user, target=target) data = serializers.serialize('json', [fav]) return HttpResponse(data, mimetype='application/javascript') else: message = (u'申し訳ありません。' u'フェイバリットメンバーにできるのは%s人までです。')\ % FavoriteUser.objects.limit request.user.message_set.create(message=message) return render_to_response_of_class(HttpResponseForbidden, '403.html')
def show_recipe(request, recipe_id=None): ''' 指定されたIDのレシピ詳細ページを出力します。 レシピがis_draft == Trueの場合、作成したユーザのみ見ることができます。 @param recipe_id: RecipeインスタンスのID @context recipe: Recipeインスタンス (recipe.id == recipe_id) @return: 403レスポンス (recipe.is_draft == True and request.user != recipe.user の場合) @return: 404レスポンス (指定されたIDのRecipeインスタンスが存在しない場合) @return: 404レスポンス (指定レシピの作成ユーザがis_active=Falseの場合 ただしレシピが商品化決定している場合を除く) @return: 200レスポンス (成功。詳細ページを表示) ''' recipe = get_object_or_404(Recipe, pk=recipe_id) recipe_user = recipe.user if not recipe.is_awarded: user_is_active_or_404(recipe_user) if recipe.is_draft and request.user != recipe_user: return render_to_response_of_class(HttpResponseForbidden, '403.html') recipe.set_request_user(request.user) comment_form = None profile = recipe_user.get_profile() if not profile.deny_comment: comment_form = forms.CommentForm() submit_form = forms.SubmitToContestForm() d = {'recipe': recipe, 'comment_form': comment_form, 'submit_form': submit_form} return render_to_response('recipes/recipe.html', d, RequestContext(request))
def register_direction(request, recipe_id=None): ''' 指定されたIDのレシピに関する作り方データを新規作成します。 レシピを作成したユーザだけが作成を行うことができます。(recipe.user==request.user) @param recipe_id: レシピID @return: 302レスポンス (ログインページへ。ログインしていない場合) @return: 403レスポンス (指定されたレシピの作成者がログインユーザではない場合) @return: 404レスポンス (指定されたIDのレシピが存在しない場合) @return: 200レスポンス (成功。DirectionインスタンスをJSONで出力) ''' recipe = get_object_or_404(Recipe, pk=recipe_id) if recipe.user != request.user: return render_to_response_of_class(HttpResponseForbidden, '403.html') form = forms.DirectionForm(request.POST, request.FILES) if not form.is_valid(): json = simplejson.dumps({'status': 'error', 'message': 'form is not valid.'}) direction = None else: direction = form.save(commit=False) recipe.add_direction(direction) direction.save() d = {'status': 'success', 'message': '', 'direction': {'pk': direction.id, 'fields': {'text': direction.text, 'photo': direction.photo and direction.photo.url or ''}}} json = simplejson.dumps(d) if direction.photo: data = '<textarea>%s</textarea>' % json else: data = json return HttpResponse(data, mimetype='text/html')
def edit_recipe(request, recipe_id=None): ''' 指定されたIDのレシピデータの変更を行います。 レシピを作成したユーザだけが変更を行うことができます。(recipe.user==request.user) forms.RecipeFormで定義された値を受け取ります。 また、複数の素材データ(食材: foodパラメータのリストと分量: quantityパラメータのリスト)を JSON文字列にエンコードします。 素材データはrecipe.decode_ingredients()でタプル(食材名,分量)のリストに 復元することができます。 @param recipe_id: レシピID @return: 302レスポンス (ログインページへ。ログインしていない場合) @return: 403レスポンス (指定されたレシピの作成者がログインユーザではない場合 一度でも公開したことがあり、既にお題にひもづいている場合) @return: 404レスポンス (指定されたIDのレシピが存在しない場合) @return: 302レスポンス (レシピ編集ページへ。成功した場合) ''' recipe = get_object_or_404(Recipe, pk=recipe_id) if (request.user != recipe.user or \ recipe.is_awarded or \ (recipe.contest and recipe.published_at)): return render_to_response_of_class(HttpResponseForbidden, '403.html') recipe.encode_ingredients(request.POST.getlist('food'), request.POST.getlist('quantity')) form = forms.RecipeForm(request.POST, request.FILES, instance=recipe) if form.is_valid(): recipe = form.save() messages.add_message(request, messages.INFO, u'レシピを保存しました。') return HttpResponseRedirect(reverse('recipes-edit', kwargs={'recipe_id': recipe.id}))
def sort_directions(request, recipe_id=None): ''' 指定されたIDのレシピにひもづく作り方データを並べ替えます。 レシピを作成したユーザだけが行うことができます。(recipe.user==request.user) POSTのdirection[]の値リストに含まれる、作り方IDの順序通りになります。 @param recipe_id: レシピID @return: 302レスポンス (ログインページへ。ログインしていない場合) @return: 404レスポンス (指定されたIDのレシピが存在しない場合) @return: 403レスポンス (指定されたレシピの作成者がログインユーザではない場合) @return: 200レスポンス (成功。DirectionインスタンスをJSONで出力) ''' recipe = get_object_or_404(Recipe, pk=recipe_id) if recipe.user != request.user: return render_to_response_of_class(HttpResponseForbidden, '403.html') direction_ids = request.POST.getlist('direction[]') direction_dict = {} for direction in recipe.direction_set.all(): direction_dict[direction.id] = direction for i, direction_id in enumerate(direction_ids): direction = direction_dict[int(direction_id)] direction.number = i direction.save() json = simplejson.dumps(direction_ids) return HttpResponse(json, mimetype='application/json')
def submit_recipe_to_contest(request, recipe_id): ''' 指定されたIDのレシピをPOSTのcontestの値で指定されたお題に投稿します。 レシピの作成ユーザだけが行うことができます。 成功後のレシピは以下の状態になります。 contest: 指定されたIDのContestインスタンス @param recipe_id: レシピID @return: 302レスポンス (ログインページへ。ログインしていない場合) @return: 404レスポンス (指定されたIDのレシピが存在しない場合) @return: 403レスポンス (ログインユーザが作成者ではない場合) @return: 403レスポンス (TODO: 指定のお題が存在しない場合) @return: 200レスポンス (レシピのJSONデータを返す。成功した場合) ''' recipe = get_object_or_404(Recipe, pk=recipe_id) if request.user != recipe.user: return render_to_response_of_class(HttpResponseForbidden, '403.html') contest_id = request.POST.get('contest', None) if contest_id: contest = Contest.objects.get(pk=contest_id) recipe.contest = contest recipe.save() json = serializers.serialize('json', [contest]) else: json = '' return HttpResponse(json, mimetype='application/json')
def validate(request, key=None): ''' ユーザをアクティベートします。 指定されたkeyを持つUserProfileインスタンスを検索し、そのuserインスタンスの is_activeをTrueに設定します。 UserProfileインスタンスのkey_issued_atが2日以上古い場合、403エラーを返します。 @context created_user: アクティベートされたユーザ @context profile: ユーザプロファイル @param key: バリデーションキー @return: 200レスポンス (成功。) @return: 403レスポンス (UserProfileインスタンスのkey_issued_atが2日以上古い場合) @return: 404レスポンス (該当のUserProfileインスタンスが存在しない場合) ''' profile = get_object_or_404(UserProfile, validation_key=key) if not profile.validate(key): return render_to_response_of_class(HttpResponseForbidden, '403.html') profile.disable_validation_key() profile.save() user = profile.user user.is_active = True user.save() d = {'created_user': user, 'profile': profile} return render_to_response('registration/new_success.html', d, RequestContext(request))
def delete_direction(request, recipe_id=None, direction_id=None): ''' 指定されたIDの作り方データを削除します。 レシピを作成したユーザだけが行うことができます。(recipe.user==request.user) @param recipe_id: レシピID @return: 302レスポンス (ログインページへ。ログインしていない場合) @return: 404レスポンス (指定されたIDのレシピが存在しない場合) @return: 403レスポンス (指定されたレシピの作成者がログインユーザではない場合) @return: 403レスポンス (指定の作り方が指定のレシピにひもづいていない場合) @return: 200レスポンス (成功。DirectionインスタンスをJSONで出力) ''' recipe = get_object_or_404(Recipe, pk=recipe_id) if recipe.user != request.user: return render_to_response_of_class(HttpResponseForbidden, '403.html') direction = get_object_or_404(Direction, pk=direction_id) if recipe != direction.recipe: return render_to_response_of_class(HttpResponseForbidden, '403.html') json = serializers.serialize('json', [direction]) direction.delete() return HttpResponse(json, mimetype='application/json')
def show_recipe_for_print(request, recipe_id=None): ''' 指定されたIDのレシピ詳細ページ(印刷向け)を出力します。 条件はshow_recipeと同じです。 ''' recipe = get_object_or_404(Recipe, pk=recipe_id) if not recipe.is_awarded: user_is_active_or_404(recipe.user) if recipe.is_draft and request.user != recipe.user: return render_to_response_of_class(HttpResponseForbidden, '403.html') recipe.set_request_user(request.user) d = {'recipe': recipe} return render_to_response('recipes/recipe_print.html', d, RequestContext(request))
def approve_comment(request, comment_id): ''' コメントを承認します。これにより他のユーザにコメントが見えるようになります。 承認できるのはコメント先のレシピを作成したユーザだけです。 @param comment_id: コメントID @return: 302レスポンス (ログインページへ。ログインしていない場合) @return: 403レスポンス (ログインユーザがレシピの作成者でない場合) @return: 404レスポンス (指定されたIDのコメントが存在しない場合) @return: 200レスポンス (成功。コメントのJSONデータを返す) ''' comment = get_object_or_404(Comment, pk=comment_id) if request.user != comment.owner: return render_to_response_of_class(HttpResponseForbidden, '403.html') comment.approve() comment.save() json = serializers.serialize('json', [comment]) return HttpResponse(json, mimetype='application/json')
def vote_to_recipe(request, recipe_id=None): ''' 指定されたIDのレシピに投票します。 レシピ作成者ではないログインユーザだけが行うことができます。 @param recipe_id: レシピID @return: 302レスポンス (ログインページへ。ログインしていない場合) @return: 403レスポンス (ログインユーザがレシピの作成者である場合) @return: 404レスポンス (指定されたIDのレシピが存在しない場合、または作成者がis_active=Falseの場合) @return: 200レスポンス (成功。VoteインスタンスをJSONで出力) ''' recipe = get_object_or_404(Recipe, pk=recipe_id) user_is_active_or_404(recipe.user) if recipe.user == request.user: return render_to_response_of_class(HttpResponseForbidden, '403.html') vote = recipe.vote(request.user) recipe.save() data = serializers.serialize('json', [vote]) return HttpResponse(data, mimetype='application/json')
def comment_to_recipe(request, recipe_id=None): ''' 指定されたIDのレシピにコメントします。 ログインユーザだけが行うことができます。 POSTする項目はCommentFormの定義に従います。 作成成功時、ログインユーザがレシピの作成者の場合は、is_moderatedはTrueになります。 それ以外の場合はFalseになり、レシピ閲覧画面に表示されません。 @param recipe_id: レシピID @return: 302レスポンス (ログインページへ。ログインしていない場合) @return: 403レスポンス (指定レシピの作成者がprofile.deny_comment == Trueの場合) @return: 404レスポンス (指定されたIDのレシピが存在しない場合、または作成者がis_active=Falseの場合) @return: 200レスポンス (not form.is_valid()の場合、フォームを再表示) @return: 302レスポンス (成功。レシピ閲覧ページにリダイレクトする) ''' recipe = get_object_or_404(Recipe, pk=recipe_id) recipe_user = recipe.user user_is_active_or_404(recipe_user) profile = recipe_user.get_profile() if profile.deny_comment: return render_to_response_of_class(HttpResponseForbidden, '403.html') form = forms.CommentForm(request.POST, request.FILES) if not form.is_valid(): message = u'コメント内容に問題があります。' messages.add_message(request, messages.INFO, message) d = {'recipe': recipe, 'comment_form': form, 'submit_form': forms.SubmitToContestForm()} return render_to_response('recipes/recipe.html', d, RequestContext(request)) comment = form.save(commit=False) comment.user = request.user comment.recipe = recipe comment.owner = recipe_user if recipe_user == request.user: comment.approve() message = u'コメントが登録されました。' else: message = u'コメントを受け付けました。%s さんが承認すると表示されます。' % recipe_user.first_name comment.save() messages.add_message(request, messages.INFO, message) return HttpResponseRedirect(reverse('recipes-show', kwargs={'recipe_id': recipe.id}))
def delete_comment(request, comment_id): ''' コメントを削除します。 削除できるのはコメントしたユーザかコメント先のレシピを作成したユーザだけです。 @param comment_id: コメントID @return: 302レスポンス (ログインページへ。ログインしていない場合) @return: 404レスポンス (指定されたIDのコメントが存在しない場合) @return: 403レスポンス (ログインユーザがレシピ、コメントの作成者でない場合) @return: 200レスポンス (成功。コメントのJSONデータが返ります) ''' comment = get_object_or_404(Comment, pk=comment_id) if request.user not in (comment.owner, comment.user): return render_to_response_of_class(HttpResponseForbidden, '403.html') json = serializers.serialize('json', [comment]) if comment.is_moderated: recipe = comment.recipe recipe.delete_comment(comment) recipe.save() comment.delete() return HttpResponse(json, mimetype='application/json')
def toggle_recipe_open_state(request, recipe_id=None): ''' 指定されたIDのレシピの公開状態を変更します。 レシピが下書き状態(is_draft==True)の場合、公開状態(is_draft==False)に変更します。 公開状態の場合、下書き状態に変更します。 レシピを作成したユーザだけが状態の変更を行うことができます。(recipe.user==request.user) @param recipe_id: レシピID @return: 302レスポンス (ログインページへ。ログインしていない場合) @return: 403レスポンス (指定されたレシピの作成者がログインユーザではない場合 商品化が決定している場合) @return: 404レスポンス (指定されたIDのレシピが存在しない場合) @return: 200レスポンス (JSONが返される。成功した場合) ''' recipe = get_object_or_404(Recipe, pk=recipe_id) if request.user != recipe.user or recipe.is_awarded: return render_to_response_of_class(HttpResponseForbidden, '403.html') recipe.toggle_open_state() recipe.save() data = serializers.serialize('json', [recipe]) # TODO: 情報を削減 return HttpResponse(data, mimetype='application/json')
def remove_favorite_user(request, user_id=None): ''' 指定されたIDのユーザをログインユーザのフェイバリットから削除します。 該当のFavoriteUserインスタンスを作成したユーザだけが削除を行うことが出来ます。 成功した場合、削除されたFavoriteRecipeインスタンスがJSONで返ります。 @param user_id: ユーザID @return: 302レスポンス (ログインページへ。ログインしていない場合) @return: 403レスポンス (FavoriteUserインスタンスを作成していない場合) @return: 404レスポンス (指定されたIDのユーザをフェイバリットにしていない場合) @return: 200レスポンス (成功。FavoriteUserインスタンスをJSONで出力) ''' target = get_object_or_404(User, pk=user_id) if target == request.user: return render_to_response_of_class(HttpResponseForbidden, '403.html') try: fav = FavoriteUser.objects.get(user=request.user, target=target) data = serializers.serialize('json', [fav]) fav.delete() except: raise Http404 return HttpResponse(data, mimetype='application/javascript')
def delete_recipe(request, recipe_id=None): ''' 指定されたIDのレシピを削除します。 レシピを作成したユーザだけが行うことができます。(recipe.user==request.user) @param recipe_id: レシピID @return: 302レスポンス (ログインページへ。ログインしていない場合) @return: 403レスポンス (指定されたレシピの作成者がログインユーザではない場合 商品化が決定している場合) @return: 404レスポンス (指定されたIDのレシピが存在しない場合) @return: 302レスポンス (POSTのredirect_pathの値、 またはsettings.LOGIN_REDIRECT_URLへ。成功した場合) ''' redirect_path = request.POST.get('redirect_path', settings.LOGIN_REDIRECT_URL) recipe = get_object_or_404(Recipe, pk=recipe_id) if recipe.user != request.user or recipe.is_awarded: return render_to_response_of_class(HttpResponseForbidden, '403.html') message = u'%s を削除しました。' % recipe.name recipe.delete() messages.add_message(request, messages.INFO, message) return HttpResponseRedirect(redirect_path)
def remove_favorite_recipe(request, recipe_id=None): ''' 指定されたIDのレシピをログインユーザのフェイバリットから削除します。 該当のFavoriteRecipeインスタンスを作成したユーザだけが削除を行うことができます。 成功した場合、削除されたFavoriteRecipeインスタンスがJSONで返ります。 @param recipe_id: レシピID @return: 302レスポンス (ログインページへ。ログインしていない場合) @return: 403レスポンス (ログインユーザがレシピの作成者である場合) @return: 403レスポンス (ログインユーザが該当のFavoriteRecipeインスタンスを作成していない場合) @return: 404レスポンス (指定されたIDのレシピが存在しない場合) @return: 200レスポンス (成功。FavoriteRecipeインスタンスをJSONで出力) ''' recipe = get_object_or_404(Recipe, pk=recipe_id) if recipe.user == request.user: return render_to_response_of_class(HttpResponseForbidden, '403.html') try: fav = FavoriteRecipe.objects.get(user=request.user, recipe=recipe) data = serializers.serialize('json', [fav]) fav.delete() except: raise Http404 return HttpResponse(data, mimetype='application/json')
def add_favorite_recipe(request, recipe_id=None): ''' 指定されたIDのレシピをログインユーザのフェイバリットに登録します。 レシピを作成したユーザを除くユーザだけが作成を行うことができます。(recipe.user!=request.user) JSONで返されるFavoriteRecipeインスタンスは以下の状態になっています。 user: ログインユーザ recipe: 指定されたIDのRecipeインスタンス @param recipe_id: レシピID @context favorite_recipe: 作成されたFavoriteRecipeインスタンス @return: 302レスポンス (ログインページへ。ログインしていない場合) @return: 403レスポンス (指定されたレシピの作成者がログインユーザの場合) @return: 404レスポンス (指定されたIDのレシピが存在しない場合、または作成者がis_active=Falseの場合) @return: 200レスポンス (成功。FavoriteRecipeインスタンスをJSONで出力) ''' recipe = get_object_or_404(Recipe, pk=recipe_id) user_is_active_or_404(recipe.user) if recipe.user == request.user: return render_to_response_of_class(HttpResponseForbidden, '403.html') fav = recipe.favorite(request.user) data = serializers.serialize('json', [fav]) return HttpResponse(data, mimetype='application/json')
def edit_recipe(request, recipe_id=None): ''' 指定されたIDのレシピの編集画面を表示します。 レシピを作成したユーザだけが表示を行うことができます。(recipe.user==request.user) @param recipe_id: レシピID @context recipe: Recipeインスタンス @context directions: クエリセット。recipe.direction_set.all() @context form: RecipeFormインスタンス @context direction_form: DirectionFormインスタンス @return: 302レスポンス (ログインページへ。ログインしていない場合) @return: 403レスポンス (指定されたレシピの作成者がログインユーザではない場合 一度でも公開したことがあり、既にお題にひもづいている場合) @return: 404レスポンス (指定されたIDのレシピが存在しない場合) @return: 200レスポンス (成功。フォームを表示) ''' recipe = get_object_or_404(Recipe, pk=recipe_id) if (request.user != recipe.user or \ recipe.is_awarded or \ (recipe.contest and recipe.published_at)): return render_to_response_of_class(HttpResponseForbidden, '403.html') form = forms.RecipeForm(instance=recipe) return render_edit_recipe_page(request, recipe, form)
def validate_change_email(request, user_id=None, key=None): ''' メールアドレス変更を行います。 @param user_id: 変更を行うユーザのID @param key: 変更のためのバリデーションキー @return: 403レスポンス (キーが正しくない場合) @return: 200レスポンス (成功) ''' user = get_object_or_404(User, pk=user_id) profile = user.get_profile() if profile.validate(key): profile.disable_validation_key() profile.save() user.email = profile.pending_email user.username = forms.email_to_username(user.email) user.save() d = {'title': u'メールアドレスの変更完了', 'text': u'メールアドレスの変更が完了しました。'} return render_to_response('base_message.html', d, RequestContext(request)) else: return render_to_response_of_class(HttpResponseForbidden, '403.html')
def submit_recipe(request, contest_id=None, recipe_id=None): ''' 指定されたIDのお題に指定されたIDのレシピを投稿します。 投稿されたレシピは、recipe.contest = contestとなります。 レシピの作成者でなければ投稿を行うことはできません。 また、既にお題にひもづいているレシピを再投稿することはできません。 @param contest_id: ContestインスタンスのID @param recipe_id: RecipeインスタンスのID @return: 200レスポンス (成功。JSONを返す) @return: 302レスポンス (ログインしていない場合。ログインページへ) @return: 403レスポンス (recipe.context != None or request.user != recipe.user の場合) @return: 404レスポンス (指定されたIDのRecipe, Contestインスタンスが存在しない場合) ''' contest = get_object_or_404(Contest, pk=contest_id) recipe = get_object_or_404(Recipe, pk=recipe_id) if recipe.user != request.user or recipe.contest: return render_to_response_of_class(HttpResponseForbidden, '403.html') recipe.contest = contest recipe.save() data = serializers.serialize('json', [recipe]) return HttpResponse(data, mimetype='application/javascript')